Ankündigung

Einklappen
Keine Ankündigung bisher.

Wie kommuniziert die ETS mit KNX-Geräten (z.B. beim partiellen Programmieren)

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

    Wie kommuniziert die ETS mit KNX-Geräten (z.B. beim partiellen Programmieren)

    Auskoppelung aus dem Thread "ESP8266 KNX mit ETS", hier soll näher beleuchtet werden, wie die Kommunikation der ETS mit den Geräten läuft und wie man das bei Eigententwicklungen besser unterstützen kann. Der Initialpost von mir war der:

    Hi,

    hier nochmal ein paar Infos, wie man die ETS zum schnelleren Programmieren bewegen kann mit partieller Programmierung. Das sind erstmal Versuche und Zwischenergebnisse, mir ist noch nicht klar, was alles im Stack gemacht werden muss, damit das alles rund läuft. Vor allem auch, weil es wohl hier noch ein Issue gibt: https://github.com/thelsing/knx/issues/93. Aber ich wollte mit euch die Erkenntnisse teilen, auch wenn ich noch nicht wirklich weiß, was ich da mache.

    Ich habe eine SysetmB-Applikation bei meinen Geräten gefunden (MDT-IP-Schnittstelle, die 2. Applikation, also der email-client und Zeitserver). Da hab ich nur einen Parameter geändert und war beeindruckt, dass beim partiellen Programmieren nur 1-Byte vom Parameterblock übertragen wurde !!!
    # Zeit Dienst Flags Prio Quelladresse Quellname Zieladresse Zielname Rout Typ DPT Info
    155 27.03.2021 14:29:22,131 zum Bus System 1.0.250 ETS 1.0.3 SCN-IP000.02 IP Interface mit Email Funktion 6 MemoryWrite (S=7) Count=1, Address=$16E9, Data=$0A
    Ich hab auch den Parameter von 9 auf 10 geändert!
    Programmierzeit war hier nur 7 Sekunden, der Parameterblock ist eigentlich Size="3972" , also fast 4k.

    Code:
    Start: 14:29:19
    Ende: 14:29:26
    Man erkennt bei der Programmierung, dass Property 27 (PID_MCB_TABLE) mehrfach abgefragt wird, vor der Programmierung
    # Zeit Dienst Flags Prio Quelladresse Quellname Zieladresse Zielname Rout Typ DPT Info
    109 27.03.2021 14:29:20,980 vom Bus System 1.0.3 SCN-IP000.02 IP Interface mit Email Funktion 1.0.250 ETS 6 PropertyValueResponse (S=13) ObjectIndex=4, PropertyId=27, Count=1, StartIndex=1, Data=00 00 0F 84 00 FF 56 3E
    wie auch nach der Programmierung
    # Zeit Dienst Flags Prio Quelladresse Quellname Zieladresse Zielname Rout Typ DPT Info
    178 27.03.2021 14:29:22,734 vom Bus System 1.0.3 SCN-IP000.02 IP Interface mit Email Funktion 1.0.250 ETS 6 PropertyValueResponse (S=13) ObjectIndex=4, PropertyId=27, Count=1, StartIndex=1, Data=00 00 0F 84 00 FF BD C8
    Mit jeweils unterschiedlichen CRC-Werten. Aber die Applikation hat nur einen Parameter-Block. Allerdings steht da irgend ein serialisierter Wert in der knxprod, den ich nicht verstehe:
    Code:
    <Code>
        <RelativeSegment Id="M-0083_A-0133-10-8772_RS-04-00000" Offset="0" Size="3972" LoadStateMachine="4">
            <Data>BQAAAAAAAAAAAgEBDwAAAAAAAAAAAAAAAAAAAAAAAA AA ...</Data>
        </RelativeSegment>
    </Code>
    Ich hab das <Data> abgekürzt, scheint der Parameterblock als Binärwert irgendwie encoded dargestellt zu sein. Ich denke, in Relation dazu werden die Deltas berechnet.

    Für die Abfrage des Property 27 ist folgender Teil der knxprod verantwortlich:
    Code:
    <LoadProcedure MergeId="7">
        <LdCtrlLoadImageProp ObjIdx="1" PropId="27" />
        <LdCtrlLoadImageProp ObjIdx="2" PropId="27" />
        <LdCtrlLoadImageProp ObjIdx="3" PropId="27" />
        <LdCtrlLoadImageProp ObjIdx="4" PropId="27" />
    </LoadProcedure>
    und für das unterschiedliche Handling für komplette Programmierung und partielle Programmierung der Teil:
    Code:
    <LoadProcedure MergeId="2">
        <LdCtrlRelSegment LsmIdx="4" Size="3972" Mode="1" Fill="0" AppliesTo="full" />
        <LdCtrlRelSegment LsmIdx="4" Size="3972" Mode="0" Fill="0" AppliesTo="par" />
    </LoadProcedure>
    <LoadProcedure MergeId="4">
        <LdCtrlWriteRelMem ObjIdx="4" Offset="0" Size="3972" Verify="true" AppliesTo="full,par" />
    </LoadProcedure>
    Warum ich mir da so sicher bin: Ich habe beide Teile in meine knxprod eingebaut (natürlich mit der korrekten Size) und prompt bei Programmieren die Fehlermeldung bekommen, dass versucht wird, auf einen geschützten Speicherbereich zuzugreifen, unmittelbar nach dem Versuch, PID 27 zu lesen. Dann habe ich nur die Einträge für LoadProcedure mit MergeId 7 entfernt und MergeId 2 und 4 so gelassen und schon hat die ETS beim kompletten Programmieren (Applikationsprogramm übertragen) den gesamten Parameterblock übertragen, beim partiellen aber nur ein Delta. Das ich aber kein Data-Tag im RelativeSegment bei mir habe, wurde das Delta scheinbar relativ zu einem Parameter-Block voller Nullen (0x00) gebildet. Zumindest sieht es so aus, als ob nur Parameter != 0 übertragen werden.
    Das geht schon wesentlich schneller (17 Sekunden statt 38), ich bin mir nur nicht sicher, ob das alles korrekt funktioniert. Vor allem muss ich testen, ob ein Parameter, den ich setze und später zurücknehme (also auf 0x00 setze), dann noch mit der 0x00 übertragen wird.

    Bevor ich den Thread jetzt hier zumülle: Kann sonst noch jemand was mit den Erkenntnissen anfangen? Ich kann auch komplette ETS-Gruppenmonitor-Aufzeichnungen liefern, aber das muss man auch verstehen können. Ich verstehe zwar nach und nach immer mehr, aber sicherlich noch nicht genug. Und ich weiß immer noch nicht, was ich daraus ableiten kann, um eventuell fehlende Teile im Stack zu implementieren.

    Deswegen hier erstmal Schluß für heute,
    Gruß, Waldemar

    OpenKNX www.openknx.de

    #2
    thewhobox: Mike, Deinen Eintrag kann ich nicht übernehmen, bin kein Admin

    Gruß, Waldemar
    OpenKNX www.openknx.de

    Kommentar


      #3
      mumpf Kein Problem, stand ja jetzt auch nix wirklich wichtiges in dem Post drin^^
      OpenKNX www.openknx.de | Kaenx-Creator | Dali-GW

      Kommentar


        #4
        thewhobox: Zu Deinem Punkt, extended Frames zuzulassen: So wie ich das sehe, fragt die ETS gleich am Anfang, nachdem über den DeviceDescriptor die MaskVersion abgefragt wurde, folgendes:
        # Zeit Dienst Flags Prio Quelladresse Quellname Zieladresse Zielname Rout Typ DPT Info
        60 27.03.2021 14:29:19,795 vom Bus System 1.0.3 SCN-IP000.02 IP Interface mit Email Funktion 1.0.250 ETS 6 PropertyValueResponse (S=1) ObjectIndex=0, PropertyId=56, Count=1, StartIndex=1, Data=00 37
        Das ist die PID_MAX_APDU_LENGTH, hier kommt 0x37, also 55 Byte zurück. Die einzelnen MemoryWrite laufen dann mit 52 Byte.

        Dein Kaenx muss dann nur beachten, dass es die minimale APDU des Gesamtweges nimmt, also auch die Koppler und Schnittstellen berücksichtigt.
        Mein Modul hat früher mit 254 geantwortet, es wurde aber trotzdem mit 63 angesprochen. Ich vermute somit, dass dei APDU meiner Schnittstelle 66 ist. Das habe ich bisher aber nirgendwo finden können, hab somit keine Ahnung, woher die ETS das weiß.

        Interessant ist auch das Fehlerhandling! Mein Modul hat 254 zurückgegeben, kann aber eigentlich nur 56 Byte. Das Programmieren funktionierte bis zum ersten MemoryWrite mit 63 Byte, da gab es kein ACK vom Modul. Die ETS hat dann ein Disconnect, gefolgt von einem neuen MemoryWrite mit 63 Byte gemacht. Hier gab es wieder kein ACK, dann gab es noch ein Disconnect und anschließend ging es mit APDU 15 weiter. Dadurch klappte das Programmieren immer und ich hab nicht gepeilt, dass es viel langsamer war als es hätte gehen können.

        Falls Du eine Ahnung hast, wie man PID 27 (PID_MCB_TABLE) implementiert, sag mir bitte Bescheid. Wenn ich das mal habe, wird es hoffentlich möglich sein, das Ganze noch mehr zu optimieren. Und wenn ich es schaffe,
        Code:
                    <AddressTable MaxEntries="2048" />
                    <AssociationTable MaxEntries="2048" />
        aus der knxprod auszuwerten, dann ist partielle Programmierung wohl perfekt.

        Gruß, Waldemar
        OpenKNX www.openknx.de

        Kommentar


          #5
          mumpf Ich hab mir mal die Spezifikation 3/5/3 (Seite 31 - Partial Download of the applicationprogram 1) angeschaut. Und glaube ich habe ne Idee wie das funktionieren könnte.

          Bei jedem Schreiben der Tabellen oder Speichers musst du den MCB auslesen und speichern (Schritt 12 Read and sace CRC checksum).
          Wenn du nun das nächste mal den Speicher schreiben willst, liest du vorher den MCB aus (Schritt 6 Compare CRC checksum).

          Wenn nun die CRC die gleiche ist, kannst du ja davon ausgehen, dass der Speicher genauso ist wie du ihn damals beschrieben hast, also musst du nur die Parameter schicken, die sich geändert haben (differential download algorithm, rest im Speicher ist ja noch der gleiche).
          Wenn die CRC nicht mehr die gleichen sind, dann hat jemand mit einem anderen Projekt vll etwas am Gerät geändert und du musst den gesamten Speicher nochmal neu schreiben und danach den CRC wieder speichern.

          Ich kam allerdings nicht dazu das zu testen.
          Ist bisher nur eine Theorie.

          Gruß Mike
          OpenKNX www.openknx.de | Kaenx-Creator | Dali-GW

          Kommentar


            #6
            Hi Mike,

            danke für die Info. An sich verstehe ich das ja konzeptionell, nur habe ich nirgendwo den CRC-Algorithmus gefunden, der verwendet werden soll. Das KNX-Gerät muss den CRC ja berechnen, damit der Wert dann von der ETS verglichen werden kann. Du hättest das Problem bei Kaenx ja auch, Du müsstest die Antwort von dem Gerät mit dem dir bekannten Parameterblock vergleichen, also auch dessen CRC berechnen, oder?

            Was ich gar nicht gedanklich berücksichtigt habe, ist das hier:
            Zitat von proggerKA Beitrag anzeigen
            Wenn die CRC nicht mehr die gleichen sind, dann hat jemand mit einem anderen Projekt vll etwas am Gerät geändert
            Ich bin immer gedanklich von einem Projekt ausgegangen und dann wäre nämlich eine CRC-Überprüfung nicht notwendig. So macht das natürlich mehr Sinn.

            Ich werde mir nochmal die von Dir benannten Schritte in der Spec ansehen, je öfter man liest, desto klarer werden die Details.

            Danke erstmal. Und falls Du mal was testest oder gar einen CRC-Algorithmus findest, dann sag mir Bescheid.

            Gruß, Waldemar
            OpenKNX www.openknx.de

            Kommentar


              #7
              Hi Waldemar,

              in der Onlinehilfe vom Manufacturing Tool sind auch noch einige interessante Informationen. Inwieweit das jetzt direkt hilft weiss ich nicht aber das ist eine gute Resource: https://support.knx.org/hc/en-us/art...ntial-Download

              Gruß, Julius

              Kommentar


                #8
                mumpf berechnen tut die ETS gar nix.
                Auf den Seiten die ich genannt habe steht immer am Ende "Read and Save crc cheksum" und bevor das wirkliche schreiben stattfindet wird der Crc auch nochmal ausgelesen und verglichen.

                Somit kannst theoretisch auch nen Counter einbauen, der nach jedem Programmieren eins hoch zählt.
                Ganz ohne aufwändige rechnerei.
                OpenKNX www.openknx.de | Kaenx-Creator | Dali-GW

                Kommentar


                  #9
                  Hi Mike,

                  das hab ich ja bisher komplett anders verstanden. Das bedeutet, ich kann (zumindest erstmal zum Testen) immer einen konstanten Wert zurückgeben, denn solange ich mit nur einer ETS mit einem Projekt arbeite, kann sich da auch nichts geändert haben. Das werde ich mal über Ostern ausprobieren, das wäre der Hammer!

                  Ich werde berichten, wie es ausgegangen ist.

                  Danke und Gruß, Waldemar
                  OpenKNX www.openknx.de

                  Kommentar


                    #10
                    Hi Mike,

                    ich werde das mit den Konstanten ausprobieren, aber ich hab was gefunden, was dagegen spricht: In 3.5.1, Kapitel 4.2.27.1.2 CRC (Seite 33) wird doch was von einem CRC-Algorithmus geschrieben. Ich muss den mal suchen, damit könnte man ja auch weiterkommen. Das nur zur Info...

                    Gruß, Waldemar
                    OpenKNX www.openknx.de

                    Kommentar


                      #11
                      Hallo Waldemar,

                      klar sollte das Gerät das eigentlich berechnen.
                      Allersdings wenn man sich die Ladeprozeduren anschaut laut Spec, rechnet die ETS da nix. Es wird ganz klar in Schritt 6 das MCB ausgelesen und der CRC checksum wird mit dem CRC aus dem vorherigen schreiben verglichen.
                      Da als letztes im Schritt wieder Read and Save CRC Checksum steht.
                      Screenshot 2021-03-29 094201.png
                      Auf dieser Grundlage könnte man auch nen Timestamp des letzten Änderns machen oder zum Testen immer den gleichen Wert zurück geben. Dann wird allerdings immer nur ein partieller Download gemacht (auch wenn der Speicher in einem anderen Projekt verändert wurde). Einen Versuch um zu schauen ob es funktioniert wäre es auf jeden Fall Wert.

                      Die Struktur aber des MCB sollte man beachten. Die hab ich vorher nicht gefunden gehabt.

                      Gruß Mike
                      OpenKNX www.openknx.de | Kaenx-Creator | Dali-GW

                      Kommentar


                        #12
                        Zitat von proggerKA Beitrag anzeigen
                        Die Struktur aber des MCB sollte man beachten. Die hab ich vorher nicht gefunden gehabt.
                        Bin mir nicht sicher, ob Du das gesehen hast. Das steht in 3.5.1, Kapitel 4.2.27.1.2 CRC (Seite 33).

                        Gruß, Waldemar
                        OpenKNX www.openknx.de

                        Kommentar


                          #13
                          Ja hab ich gesehen, nachdem du es oben geschrieben hast.
                          Das ist ja aber nur die Seite des KNX-Geräts, das ja die Property zur Verfügung stellt.
                          Klar, sagt die Spec dann, dass man das richtig berechnen sollte.

                          Aber wenn man sich die andere Seite von der ETS aus anschaut, wird da nix berechnet, sondern nur verglichen, ob der vorher ausgelesene CRC der gleiche ist, wie der gerade eben ausgelesene.

                          Kann auch sein, dass ich da falsch liege. Aber das auszuprobieren sollte einfacher gehen, als die Implementierung von CRC16-CCITT.
                          Ich hab auch jetzt schon mehrere Seiten und Pakete ausprobiert um auf den CRC 0xE5CC aus dem Beispiel von "123456789" zu kommen.
                          Aber alle kommen auf 0x29B1
                          Verwende das hier: Online CRC Calculator Javascript

                          Gruß Mike
                          Zuletzt geändert von thewhobox; 29.03.2021, 13:05.
                          OpenKNX www.openknx.de | Kaenx-Creator | Dali-GW

                          Kommentar


                            #14
                            Ich hab nun mal weiter geforscht, welcher algorythmus es nun genau ist.
                            Auf crccalc.com kann man die Ergebnisse von vielen Algorythmen vergleichen.
                            Dank dem Beispiel in der Spec muss es also genau "CRC-16/AUG-CCITT"
                            Dieser hat allerdings als Iinit 0x1D0F anstatt der 0xFFFF wie angegeben....

                            Mit dem Code klappt es den CRC wie im Beispiel zu berechnen:
                            Code:
                            public static ushort ComputeChecksum(byte[] bytes)
                            {
                              ushort initialValue = 0x1D0F;
                              ushort[] Table = { 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 };
                              if (bytes == null) { throw new ArgumentNullException(nameof(bytes)); }
                              if (bytes.Length == 0) { throw new ArgumentOutOfRangeException(nameof(bytes.Length)); }
                              var crc = initialValue;
                              var end = bytes.Length - 1;
                              for (int i = 0; i <= end; ++i)
                              {
                                crc = (ushort)((crc << 8) ^ Table[((crc >> 8) ^ (0xff & bytes[i]))]);
                              }
                              return crc;
                            }
                            OpenKNX www.openknx.de | Kaenx-Creator | Dali-GW

                            Kommentar


                              #15
                              YESS!!! Genial! Parallel zu Deiner Algorithmussuche hab ich es mal mit den Konstanten ausprobiert und den Stack ein bisschen gehackt. Zur Sicherheit einmal komplett programmiert, dann genau einen Parameter von 1 auf 2 geändert und dann partiell programmiert. Das Ergebnis:

                              Programmierdauer-Partiell.jpg
                              Also nur 6 Sekunden! Und:
                              # Zeit Dienst Flags Prio Quelladresse Quellname Zieladresse Zielname Rout Typ DPT Info
                              138 29.03.2021 21:04:33,317 zum Bus System 1.0.250 ETS 1.0.9 Sensormodul-1W 6 MemoryWrite (S=11) Count=1, Address=$0420, Data=$02
                              Das ist noch viel besser, als ich es zu hoffen wagte, ich ging davon aus, dass ich mindestens Kanalweise übertragen muss, was bei mir n * 110 Bytes bedeutet hätte.

                              Jetzt werde ich noch Deinen Algorithmus von oben implementieren und dann mit Thomas klären, wie bzw. ob wir das noch in den Stack bekommen (ich arbeite ja in einem fork).

                              Erstmal vielen Dank, Mike! Das hat es jetzt echt gebracht. Vor allem beim Testen von Logiken war es häufig so, dass man ein oder zwei Parameter angepasst hat und dann wieder probieren musste. Wenn dann fürs Programmieren immer 3-5 Minuten vergehen, ist das ätzend. Jetzt wird so was 6-15 Sekunden dauern!!!

                              Jetzt muss ich das noch fertig implementieren, dann ganz viel testen und dann kann ich mir ein Loch in den Bauch freuen.

                              Viele Grüße,
                              Waldemar
                              OpenKNX www.openknx.de

                              Kommentar

                              Lädt...
                              X