Ankündigung

Einklappen
Keine Ankündigung bisher.

EibPC² Einsteigerfragen

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

    EibPC² Einsteigerfragen

    Hallo zusammen,
    ich habe mich ein bisschen durch Google/das Forum gewühlt, aber finde mich nicht so ganz zu Recht, daher ein paar allgemeine Fragen zum EibPC².
    Falls das eigentlich ins Einsteigerforum gehören sollte: pardon und danke vorab für's Verschieben.

    Das Zusammenklicken von Grafikmodulen ist für mich nicht das richtige, ich will das meiste Zeug was ich mir vorstelle, damit ich es auch wirklich verstehe in Code umsetzen. Dazu benutze ich das EibPC-Handbuch und gucke mich ein wenig um. Ich habe schon TCP-Modbus verwendet um dann mit einem Wandler auf RTU-Modbus zuzugreifen.

    Jetzt fehlen mir ein paar Dinge:

    1. Nehmen wir an ich will ein Array von Werten anlegen, das ich dann fülle (Ringspeicher.. oder einfach nur ein Array an Variablen über die ich dann loopen kann).. geht das überhaupt vernünftig? Also kriege ich einen Array-Datentypen wo ich einfach 30 u8s z.B. reinlegen kann? Falls nein wie implementiert man dann generische Schleifen wo mit n verschiedenen Dingen eine vergleichbare Aktion passieren soll am besten?

    2. Ich habe eine PV-Anlage (Senec), die einige Werte über eine HTML-Seite auf einem https-interface mit javascript bereitstellt.. wie kriege ich da aktuelle Werte extrahiert? Gibt es ein Beispiel?

    3. wie funktioniert das Scheduling.. ich meine das so: Mit einer cycle(m:s), kriege ich eine Zykluszeit für eine Code-Ausführung hin. Was passiert mit dem Code außen rum? Was triggert die Ausführung davon? Weil offenbar wird er initial mindestens ausgeführt.

    4. wie starte ich einen Timer wenn eine GA eintrudelt?

    Sorry, falls das schon beschrieben ist - das werden sicher nicht die letzten Fragen sein, aber so für den Einstieg hilft mir das als Nicht-Autodidakt schon weiter falls sich jemand erbarmt Und demjenigen schon Mal vielen Dank!

    #2
    Hallo,

    ein großer Teil deiner Fragen sollte im Kapitel Objekte/Validierungsschema im Handbuch erklärt werden.

    Grundsätzlich ist die Verarbeitung nicht imperativ/sequentiell/prozedural, auch wenn es auf den ersten Blick so aussieht, sondern es wird ein Abhängigkeitsbaum erzeugt, bei dem die Ausführung eines Knotens von der Änderung seiner Abhängigkeiten angestoßen wird. Ein Beispiel dazu findest du im Handbuch.

    Deshalb gibt es auch keine for/while-Schleifen. Die Verarbeitung selbst erfolgt ja in einer impliziten, endlosen Schleife.

    Zu deinen Fragen:

    zu 1. Du kannst mit stringset/stringget Daten als Array abspeichern. Ob das für die Einzelfall passt oder notwendig ist, ist allerdings die Frage. Wenn es um das Abspeichern von Messwerten geht, bietet sich eher der timebuffer an. Für "mach' das geliche mit 1,2,3,.." bieten sich Macros an.

    zu 2. Die Werte kommen ja meist aus einem per JS angestoßenen API-Aufruf. Meist ist es einfacher, die API direkt anzuzapfen. Ich kenne die Wechselrichter nicht. Gibt es da ne Demoseite?

    zu 3. Events: Bustelegramme, timer, asynchrone Ereignisse (tcp, udp, modbus, httprequests, mqtt, ..)

    zu 4. if after("ga-1/2/3", 10000u64) then {....} endif


    Generell ist es einfacher, konkrete Aufgabenstellungen mit Beispielen zu beantworten. Kann kommt man auch schnell dahinter, wie man was ähnliches umsetzt.

    Kommentar


      #3
      Der Hinweis auf grundsätzlich nicht prozedural war wertvoll! Danke für die Antworten

      da das das erste Logik-Projekt ist, gleich mal exemplarisch die Frage zu Punkt 2:
      wie kann ich die Variablenwerte aus Vars.html bekommen (im Anhang) - beispielhaft GUI_GRID_POW aus ENERGY?
      Vars.zip

      Kommentar


        #4
        Nachtrag:

        {"CASC":{"BATPOWERSUM":"fl_C4F561E7","POWER":["fl_00000000","fl_00000000","fl_00000000","fl_0000 0000","fl_00000000","fl_00000000"],"PVGEN":["fl_00000000",[...]

        ist eine Antwort auf " curl --location -g 'https://192.168.110.245/lala.cgi' --data '{ "CASC" : {} }' --insecure", wobei die IP dabei die Adresse des Speichers in dessen VLAN ist (wie man sicher vermuten konnte)

        Wie kriege ich das jetzt als eibpc ähnlich ausgelesen und geparset?

        Kommentar


          #5
          Für die Nachwelt: - Tags Senec eibpc² curl json httprequest:

          exemplarisch:
          httprequest(POST, $https://<ip>/lala.cgi$, $$, $$, ${ "CASC" : {"POWER":""} }$, TLS_IGNORE_CERT, 20u08, 5u08, https_status, reply_header, reply_body);

          ${ "CASC" : {"POWER":""} }$ <- ist hier in JSON übermittelt das Unterelement POWER von CASC.

          Kommentar


            #6
            Neue Frage, neues Glück:
            Wie extrahiere ich eine f32 aus einem String? Ich habe den hexadezimalen Wert der schon als Float vorliegenden Variable in Ascii. Sieht im Debug-UDP-Telegram so aus:
            image.png
            jetzt will ich den Wert einfach in eine f32 haben. Das klappt aber nicht.

            In eine s32 kriege ich ihn rein. (das ist die Ausgabe nach der "4242424200" - da sieht man von ascii umgewandelt den Wert mit endianness-Verschiebung 44df1734 (34 17 df 44)
            Das habe ich geschafft mit convert($0x$+string, 0s32) - hilft mir natürlich nicht, weil die Daten jetzt eine vollkommen andere Zahl sind, fand aber interessant dass das direkt klappt.
            Wenn ich stattdessen das gleiche aber mit 0f32 mache , kriege ich einen völlig anderen Wert (0x4e89defa).. also irgendwas wird umgerechnet, aber es ist ja schon float und müsste nicht konvertiert werden.. und zuweisen von int nach float darf ich auch nicht.

            Wie kriege ich jetzt den Wert in meine float32-Variable um damit rechnen zu können? Ich suche quasi sowas wie memset(&varaddr, value, size) in C. Außerdem - wieso hex-notation nur für unsigned?
            Kannst Du helfen foobar0815?


            Zuletzt geändert von Machtin; 10.12.2023, 18:45.

            Kommentar


              #7
              Du suchst die Funktion stringcast, z.b,. beginnend an Position 8:
              Code:
              rFloat=stringcast(String,0f32,8u16)
              siehe auch im Handbuch (F1...)
              offizielles Supportforum für den Enertex® EibPC: https://knx-user-forum.de/eibpc/
              Enertex Produkte kaufen

              Kommentar


                #8
                Hi,

                da die Konvertierung ja öfter nötig ist, bietet es sich an, ein Makro dafür zu schreiben. In dem Fall muss außerdem die Endianess angepasst werden, sonst kommt Murks raus. Der EibPC verwendet LE. Die Werte hier sind als BE codiert.

                Lege dir eine neue Makrobibliothek an:
                Code:
                :begin rfmStrToFloatLE(zRaw)
                :var zB0@
                :var zB1@
                :var zB2@
                :var zB3@
                
                zB0@=convert($0x$c6 + split(zRaw, 3u16, 4u16), 0)
                zB1@=convert($0x$c6 + split(zRaw, 5u16, 6u16), 0)
                zB2@=convert($0x$c6 + split(zRaw, 7u16, 8u16), 0)
                zB3@=convert($0x$c6 + split(zRaw, 9u16, 10u16), 0)
                
                :var zVal@
                zVal@=$$c4
                if change(zB0@) then stringset(zVal@, zB0@, 0u16) endif
                if change(zB1@) then stringset(zVal@, zB1@, 1u16) endif
                if change(zB2@) then stringset(zVal@, zB2@, 2u16) endif
                if change(zB3@) then stringset(zVal@, zB3@, 3u16) endif
                
                :var fVal@
                fVal@=stringcast(zVal@, 0f32, 0u16)
                
                :return {fVal@}
                :end
                
                :begin rfmStrToFloatBE(zRaw)
                :var zB@
                zB@=convert($0x$c10 + split(zRaw, 3u16, 10u16), 0u32)
                
                :var zVal@
                zVal@=$$c4
                if change(zB@) then stringset(zVal@, zB@, 0u16) endif
                
                :var fVal@
                fVal@=stringcast(zVal@, 0f32, 0u16)
                
                :return {fVal@}
                :end​
                Und im Programm wie folgt verwenden:
                Code:
                zIn=$fl_44DF1734$ // oder parsejson....
                
                fLE=rfmStrToFloatLE(zIn) // 1.4144194437903934e-7
                fBE=rfmStrToFloatBE(zIn)​ // 1784.72509765625
                Edit: rfmStrToFloatBE() vereinfacht
                Zuletzt geändert von foobar0815; 11.12.2023, 10:47.

                Kommentar


                  #9
                  außerdem brauchst du vmtl keinen POST sondern einen GET request (das macht dein curl-Aufruf)

                  Kommentar


                    #10

                    image.png
                    -> klappt - und schon sehe ich, dass meine Frau kocht.

                    habe es minimal modifiziert, weil ich das 'fl_' im App-Code schon aus dem String werfe, aber das ändert nichts.

                    Werde mal versuchen noch zu durchschauen warum das funktioniert und wie der Gedankengang dahinter ist

                    Vielen vielen Dank!

                    Kommentar


                      #11
                      Zitat von foobar0815 Beitrag anzeigen
                      außerdem brauchst du vmtl keinen POST sondern einen GET request (das macht dein curl-Aufruf)
                      geht übrigens wirklich tatsächlich nur mit POST.. weiß nicht genau was die Kollegen bei Senec sich dabei gedacht haben, hab' aber von WebDev keine Ahnung:

                      MINGW64 ~/Downloads/github
                      $ curl -X POST --location -g 'https://192.168.110.245/lala.cgi' --data '{ "ENERGY" : {"GUI_GRID_POW":""} }' --insecure
                      {"ENERGY":{"GUI_GRID_POW":"fl_45028DC0"}}

                      ~/Downloads/github
                      $ curl -X GET --location -g 'https://192.168.110.245/lala.cgi' --data '{ "ENERGY" : {"GUI_GRID_POW":""} }' --insecure
                      <html><head><title>Not Found</title></head><body><h1>Not Found</h1><p>Resource `lala.cgi` could not be found.</p></body></html>​

                      Kommentar


                        #12
                        Und ich habe die man-page von curl nicht richtig gelesen und -g mit -G verwechselt... 😅

                        Kommentar


                          #13
                          Zitat von foobar0815 Beitrag anzeigen
                          Und ich habe die man-page von curl nicht richtig gelesen und -g mit -G verwechselt... 😅
                          auch frech definiert..

                          Nächste Frage: Wenn ich den timebuffer nehm', und jetzt nicht unbedingt Gedöns im Flash brauche (also wenn ich die Daten verliere, ist mir das egal), wie lese ich denn die aktuellen Elemente ohne, dass mich eine zeitliche Referenz interessiert? Eventuell doch falscher Ansatz mit dem Timebuffer?
                          Was ich eigentlich machen will ist tiefpassfiltern.. also Mittelwert über die letzten n Werte von der ausgelesenen Leistung.
                          Hab sie mal in 'nen timebuffer gelegt, aber darüber jetzt einen Mittelwert zu bilden scheint schwierig wenn ich mich nicht mit den Timestamps auseinandersetzen möchte.
                          Daher kam die Frage nach Arrays/Loops.

                          Der andere Fall wäre: ich habe eine Liste mit 10 Lampen und deren Status möchte ich abfragen.. also quasi was man in C so gedacht hätte:

                          #define NUMBER_OF_LIGHTS 10u [I]uint32_t list_of_light_group_addresses[NUMBER_OF_LIGHTS];
                          for(i=0;i<NUMBER_OF_LIGHTS;i++)
                          {
                          process_lights(list_of_light_group_addresses);
                          }



                          -> wie gehe ich sowas an, wenn ich jetzt in EibPC² denke?



                          Zweites Thema: kann ich keine zwei ifs nacheinander in einem if schreiben? Folgendes gibt 'nen parser-Fehler - wenn ich eins der zwei ifs bei "Scenario" lösche, kompiliert's.

                          Code:
                          if https_status == 200u16 then {
                              https_status=0u16; /* reset status to get the trigger again later */
                          
                              power_incoming_watt_string = split(parsejson(reply_body, $/ENERGY/GUI_GRID_POW$, $$c11), 3u16, 65534u16); /* get the json string that contains the incoming power (negative means outgoing) */
                              power_incoming_watt_f32 = rfmStrToFloatBE(power_incoming_watt_string);
                              senec_com_error = 0b01;
                          
                              timebufferadd(timbuff_id_grid_power_values, power_incoming_watt_f32); /* ring buffer the grid power to average it */
                              
                              //debug msg to read in wireshark: sendudp(1234u16, 192.168.1.27, power_incoming_watt_string, $BBBB$, power_incoming_watt_f32);
                              
                          //    scneario 1:
                          //    - we have 1500 watts being injected to the net in average over the last four minutes
                          //    - the heating rod is off
                          //    - the heating rod temperature is below or equal to 60° (avoid heating above in order to reduce scale (calcium carbonate))
                          //    action: switch ON heating rod rather than inject energy into the grid
                              if(power_incoming_watt_f32 < const_threshold_act_heat_rod_watt) and (aktiv_heizstab == 0u16) and (solltemp_heizstab <= 600u16) then {  
                                  mb_Statuswrite = writemodbus(uSenec, MB_HOLDING_REGISTER, mb_hr_aktiv_heizstab, 1u16, BIG_ENDIAN, BIG_ENDIAN);                      
                              }endif
                              
                              
                              /**************************************************/
                              
                              
                          //    scneario 2:
                          //    - we draw current from the grid in average
                          //    - the heating rod is on
                          //    action: switch OFF heating rod
                              if(power_incoming_watt_f32 > 0)  then {        
                                  mb_Statuswrite = writemodbus(uSenec, MB_HOLDING_REGISTER, mb_hr_aktiv_heizstab, 0u16, BIG_ENDIAN, BIG_ENDIAN);
                              }endif
                          
                          }endif
                          ​
                          P.S.:
                          Weil's mir gerade auffiel:
                          image.png
                          Zuletzt geändert von Machtin; 12.12.2023, 06:41.

                          Kommentar


                            #14
                            Hi,

                            timebuffer ist für sowas der falsche Ansatz, falls du sie nicht anzeigen willst.

                            Für den gleitenden Mittelwert würde sich stringset und stringcast anbieten, um die n Werte zu speichern, plus eine Variable für den aktuellen Mittelwert. Plus ein Zähler, der bei jedem neuen Wert ältesten Wert vom aktuellen Mittelwert abzieht und den neuen /N draufaddiert und mit stringset an der Stelle speichert.

                            Zitat von Machtin Beitrag anzeigen
                            10 Lampen und deren Status möchte ich abfrage
                            Musst du ausrollen, also für 10 Leuchten auch 10 mal das Makro hinschreiben. Mit den Makros muss zumindest process_lights nicht kopiert werden.

                            Zitat von Machtin Beitrag anzeigen
                            zwei ifs
                            Du brauchst nach dem inneren "} endif" ein Semikolon, dann sollte es gehen.


                            Zitat von Machtin Beitrag anzeigen
                            P.S.:
                            Wird korrigiert, danke.

                            Kommentar


                              #15

                              Hey
                              Kann es sein, dass Dein Makro im Fall von 00 im Wert nicht funktioniert weil das den String terminiert oder so? Finde gerade keine klügere Erklärung bei fl_41C00000 als JSON-Inhalt.
                              Habe mal Testweise das von little endian genommen und die endianness vertauscht (glaube Du hatest das mal vor dem Edit so).

                              Was mich aber noch mehr wundert:
                              image.png

                              der fval scheint auf 24° zu gehen, aber
                              bat_temperature_f32 = rfmStrToFloatBE(bat_temperature_string);
                              bleibt auf 0..?
                              Zuletzt geändert von Machtin; 18.12.2023, 07:41.

                              Kommentar

                              Lädt...
                              X