Ankündigung

Einklappen
Keine Ankündigung bisher.

Erzwingen, dass linknx ein Objekt (GA) neu ausliest

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

    Erzwingen, dass linknx ein Objekt (GA) neu ausliest

    Hallo,

    ich habe erste Versuche mit linknx gemacht. Funktioniert auch soweit gut. Jetzt möchte ich meine Raumcontroller überwachen, da diese bei einem Stromausfall und auch nach dem Programmieren bestimmte Einstellungen "vergessen".

    Dazu habe ich eine rule erstellt, die alle 60 Sekunden eine Adresse auswertet, die der Raumcontroller beim Programmieren zurücksetzt. Abhängig vom Ergebnis der Abfrage kann ich dann den Status auf "OK" oder "Nicht OK" setzen und auf meinem Raumpanel visualisieren.

    Nun mein Problem: linknx verwendet zur Auswertung einer condition den letzten Wert der entsprechenden Objekte. Ich möchte aber, dass die GAs jedes Mal neu ausgelesen werden.

    Wie kann ich das erzwingen?

    Danke vorab und Gruß
    Peter

    #2
    Habs jetzt so gemacht, dass ich zunächst eine rule definiert habe, die alle relevanten Objekte regelmäßig ausliest (send-read-request), danach kommen die rules, die überprüfen, ob die Raumcontroller noch im Normalzustand sind.

    Falls es eine elegantere Lösung gibt, dann bin ich froh drum :-)

    Kommentar


      #3
      Hi,

      send-read-request ist schon das Mittel der Wahl. Ob etwas eleganter geht, als Du es gelöst hast, kann man nur sagen, nachdem Du Deine Lösung hier geposted hast...

      Gruß, Waldemar
      OpenKNX www.openknx.de

      Kommentar


        #4
        Zitat von mumpf Beitrag anzeigen
        Ob etwas eleganter geht, als Du es gelöst hast, kann man nur sagen, nachdem Du Deine Lösung hier geposted hast...
        Hast recht, Waldemar!

        Damit Ihr auch das Umfeld kennt: es läuft auf einem Raspi mit dem Image von Michael.

        So werden eibd und linknx gestartet:
        Code:
        /usr/local/bin/eibd -c -S -D -i -T -d -u --eibaddr=1.1.100 --pid-file=/var/run/eibd.pid usb:1:4
        /usr/local/bin/linknx -c/var/lib/linknx/linknx.xml -p /var/run/linknx.pid -d/var/log/linknx.log -w
        Und hier der relevante Code für mein Anliegen:

        HTML-Code:
        <?xml version="1.0" ?>
        <config>
          <objects>
        
            <!-- RCD-Solltemperatur. Dient als Indikator, ob RCD gebootet wurde -->
            <object type="9.xxx" id="Buero.RCD.Solltemperatur" gad="10/7/8" log="true" flags="cwu" init="0">0</object>
        
            <!-- Statusanzeige auf Controlpanel -->
            <object type="16.001" id="Buero.RCD.Status.Txt" gad="10/7/100" log="true" flags="cwutf" >Status RCD Buero Text</object>
            <object type="1.001" id="Buero.RCD.Status.EA" gad="10/7/101" log="true" flags="cwutf" >Status RCD Buero EA</object>
          </objects>
          
          <rules>
            <!-- regelmäßig Solltemperatur lesen -->
            <rule id="All.RCD.ReadStatus">
              <condition type="timer" trigger="true">
                <every>30</every>
              </condition>
              <actionlist>
                <action type="send-read-request" id="Buero.RCD.Solltemperatur" />
              </actionlist>
            </rule>
        
            <!-- regelmäßig prüfen, ob Solltemperatur =0 -->
            <rule id="Buero.RCD.CheckStatus">
              <condition type="timer" trigger="true">
                <every>30</every>
              </condition>
              <actionlist>
                <action type="conditional">
                  <condition type="object" id="Buero.RCD.Solltemperatur" value="0" />
        		    <!-- Solltemperatur=0 ==> RCD wurde zurückgesetzt -->
                    <action type="set-value" id="Buero.RCD.Status.Txt" value="Boot" />
                    <action type="set-value" id="Buero.RCD.Status.EA" value="0" />
                </action>
                <action type="conditional">
                  <condition type="object" id="Buero.RCD.Solltemperatur" op="ne" value="0" />
        		    <!-- Solltemperatur<>0 ==> RCD läuft normal -->
                    <action type="set-value" id="Buero.RCD.Status.Txt" value="OK" />
                    <action type="set-value" id="Buero.RCD.Status.EA" value="1" />
                </action>
              </actionlist>
            </rule>
          </rules>
        
          <services>
            <xmlserver type="inet" port="1028" />
            <knxconnection url="ip:192.168.1.199" />
            <persistence type="file" path="/var/lib/linknx/persist"/>
            <exceptiondays>
            </exceptiondays>
            <location lon="9.3469069" lat="48.624421"/>
            <ioports>
            </ioports>    
          </services>
          <logging output="/var/log/linknx.log" format="%d{%Y%m%d %H:%M:%S,%l} %5p %c %x: %m%n" level="INFO"/>
        </config>    
        Meine Frage ist, ob ich in der rule CheckStatus erzwingen kann, dass die Solltemperatur aktuell gelesen wird oder ob es nur so geht, wie ich es gelöst habe.

        Ist etwas lang geworden, sorry!

        Gruß
        Peter

        Kommentar


          #5
          Hallo Peter,

          das mit dem read-request weiß ich auch nicht anders, das ist eben der Ersatz für Busteilnehmer, die nicht selbst senden können.

          Aber der 2. Teil geht "eleganter", da musst Du nicht mehr periodisch prüfen, sondern kannst direkt auf die 0 reagieren:
          Code:
              <!-- prüfen, ob Solltemperatur =0 -->
              <rule id="Buero.RCD.CheckStatus">
                <condition type="object" id="Buero.RCD.Solltemperatur" value="0" trigger="true"/>
                <actionlist>
                  <!-- Solltemperatur=0 ==> RCD wurde zurückgesetzt -->
                  <action type="set-value" id="Buero.RCD.Status.Txt" value="Boot" />
                  <action type="set-value" id="Buero.RCD.Status.EA" value="0" />
                </actionlist>
                <actionlist type="on-false">
           	<!-- Solltemperatur<>0 ==> RCD läuft normal -->
                  <action type="set-value" id="Buero.RCD.Status.Txt" value="OK" />
                  <action type="set-value" id="Buero.RCD.Status.EA" value="1" />
                </actionlist>
              </rule>
          Hat auch den Vorteil, dass die Regel unmittelbar nach dem Response feuert - bei Dir könnte es passieren, dass der read-request verschickt wird, die check-rule direkt danach läuft und der Response noch nicht da ist. Dann würde der Status erst nach weiteren 30 Sek. aktualisiert werden. Bei meinem Vorschlag aber unmittelbar nach dem Response, egal wann der eintrifft. Ist aber in diesem Szenario nicht so kriegsentscheidend...

          Gruß, Waldemar
          OpenKNX www.openknx.de

          Kommentar


            #6
            Hallo Waldemar,

            danke. Guter Punkt, das hab ich total übersehen, weil meine Ursprungsidee ja eine andere war.

            Gruß
            Peter

            Kommentar


              #7
              Hallo Waldemar,

              ich hab das eingebaut. Wenn jetzt linknx neu startet und der RCD gebootet wurde, dann wird CheckStatus nie durchgeführt. ich hab dann bei der rule noch ein init="true" dazugemacht, um zu erzwingen, dass sie beim Start von linknx geprüft wird. Im Log ist aber nichts zu sehen.

              Wo liegt mein Fehler?

              Gruß
              Peter

              Kommentar


                #8
                Hi Peter,

                ich sehe an der Logik keine Fehler - hier müsste man das Log auswerten.
                Hast Du im Gruppenmonitor geschaut, ob wirklich eine 0 nach dem boot ankommt? Und vorher ein anderer Wert?

                Übrigens: Damit eine Rule beim Startup ausgeführt wird, muss man init="eval" machen. Wenn Du init="true" machst, sagst Du nur, dass die rule nach dem start auf 1 ist und das erste mal beim Übergang von 1 auf 0 ausgelöst wird.

                Und Du solltest Dein Buero.RCD.Solltemperatur auf init="request" setzen, damit er beim Start den richtigen Wert hat.

                Gruß,
                Waldemar
                OpenKNX www.openknx.de

                Kommentar


                  #9
                  Hallo Waldemar,

                  zunächst Danke für den Tipp mit init="eval". Das wusste ich nicht und ist auch im linknx-Wiki anders dokumentiert:

                  the attribute init="false" (default) of the rule is controlling the re-evaluation during startup. if set to "true" the rule will be reevaluated on restart of linknx
                  Leider sendet mein RCD gar keinen Wert für die Solltemperatur, solange nicht die Komforttemperatur, Heizen/Kühlen und Nacht/Standby/Komfortbetrieb gesetzt sind.

                  Deshalb habe ich die Lösung so abgewandelt, dass ich vor der Abfrage der Solltemperatur das entsprechende Objekt auf 0 setze. Die Flags des Objekts Solltemperatur sind so eingestellt, dass linknx keinen Wert auf den Bus sendet.

                  Jetzt kann ich aber nicht mehr auf die Änderung der Solltemperatur reagieren, denn ich weiß nicht, ob sie sich ändert, weil ich sie auf 0 gesetzt habe oder weil der RCD einen Wert gesendet hat. Deshalb und auch weil ich 10 RCDs habe, habe ich mich ein wenig mit LUA-Scripting beschäftigt ein Script entwickelt, das alle RCDs abfragt.

                  Für diejenigen, die vielleicht ein ähnliches Problem haben, hier meine Lösung:

                  Dazu habe ich zunächst die RCDs als Tabelle mit einer Nummerierung von RCD.1 bis RCD.10 definiert, damit ich sie später der Reihe nach abfragen kann:

                  HTML-Code:
                  		<!-- Tabelle mit RCDs ==========================================================================================-->
                  <object type="28.001" id="RCD.1" init="WZ">WZ</object>
                  <object type="28.001" id="RCD.2" init="Kueche">Kueche</object>
                  <object type="28.001" id="RCD.3" init="Schlafen">Schlafen</object>
                  <object type="28.001" id="RCD.4" init="Bad_EG">Bad_EG</object>
                  <object type="28.001" id="RCD.5" init="Kind1">Kind1</object>
                  <object type="28.001" id="RCD.6" init="Kind2">Kind2</object>
                  <object type="28.001" id="RCD.7" init="Gaeste">Gaeste</object>
                  <object type="28.001" id="RCD.8" init="Bad_OG">Bad_OG</object>
                  <object type="28.001" id="RCD.9" init="Buero">Buero</object>
                  <object type="28.001" id="RCD.10" init="Hobby">Hobby</object>

                  Dann zu jedem RCD sämtliche Parameter:
                  HTML-Code:
                  		<!-- HG 10 = Buero (Büro) ---------------------------------------------------------------------------------------->
                  <object type="1.001"  id="Buero.RCD.Komfortbetrieb"       gad="10/7/3"   init="persist" log="true"               >Komfortbetrieb Buero</object>
                  <object type="1.001"  id="Buero.RCD.Nacht_Standbybetrieb" gad="10/7/4"   init="persist" log="true"               >Nach Standby Buero</object>
                  <object type="9.xxx"  id="Buero.RCD.Solltemperatur"       gad="10/7/8"   init="0" log="true" flags="cwu"         >0</object>
                  <object type="9.xxx"  id="Buero.RCD.Komforttemperatur"    gad="10/7/15"  init="persist" log="true"               >Komforttemperatur Buero</object>
                  <object type="1.001"  id="Buero.RCD.Heizen_Kuehlen"       gad="10/7/20"  init="persist" log="true"               >Heizen Kuehlen Buero</object>	
                  <object type="16.001" id="Buero.RCD.Status.Txt"           gad="10/7/100" init=""        log="true" flags="cwutf" >Status RCD Buero Text</object>
                  <object type="7.xxx"  id="Buero.RCD.AnzOK"                gad="10/7/101" init="persist" log="true"               >Anzahl OK RCD Buero</object>
                  <object type="7.xxx"  id="Buero.RCD.Anz_init"             gad="10/7/102" init="persist" log="true"               >Anzahl init RCD Buero</object>
                  Abfragen der Solltemperatur (alle 15 Minuten):
                  HTML-Code:
                  <action type="set-value" id="Buero.RCD.Solltemperatur" value="0" />
                  <action type="send-read-request" id="Buero.RCD.Solltemperatur" />
                  Und dann das Prüfen des Status samt Initialisierung und einer Statistik, wie oft der Status OK war oder nicht. Auf mein zentrales Panel wird ein String geschickt, an dem ich den aktuellen Status sehe, sowie die Anzahl OK/init. Damit kann ich sehen, wenn irgendwo etwas nicht stimmt.
                  HTML-Code:
                  <action type="script">
                    
                    --[[ wandelt den Objektstatus eines Switch (on/off) in einen Zahlenwert (0/1) um ]]
                    function switch2number(_switch)
                  	if _switch == "on" then
                  	  return 1
                  	else
                  	  return 0
                  	end
                    end
                  
                    --[[ initialisiert den RCD im Raum RCD_Name_init ]]
                    function initRCD(RCD_Name_init)
                  	set(RCD_Name_init .. ".RCD.Komfortbetrieb", switch2number(obj(RCD_Name_init .. ".RCD.Komfortbetrieb")));
                  	set(RCD_Name_init .. ".RCD.Nacht_Standbybetrieb", switch2number(obj(RCD_Name_init .. ".RCD.Nacht_Standbybetrieb")));
                  	set(RCD_Name_init .. ".RCD.Komforttemperatur", obj(RCD_Name_init .. ".RCD.Komforttemperatur"));
                  	set(RCD_Name_init .. ".RCD.Heizen_Kuehlen", switch2number(obj(RCD_Name_init .. ".RCD.Heizen_Kuehlen")));
                    end
                    
                  
                    sleep(10);
                    --[[ alle RCDs durchgehen ]]
                    for RCD = 1,10,1 do
                  	RCD_Name = obj("RCD." .. RCD);
                  	--[[ wenn Solltemperatur = 0, dann müssen die Werte für das RCD neu initialisiert werden ]]
                  	if tonumber(obj(RCD_Name .. ".RCD.Solltemperatur")) == 0 then
                  	  initRCD(RCD_Name);
                  	  --[[ dann noch Statistik ]]
                  	  set(RCD_Name .. ".RCD.Anz_init", obj(RCD_Name .. ".RCD.Anz_init") + 1);
                  	  set(RCD_Name .. ".RCD.Status.Txt","-:" .. obj(RCD_Name .. ".RCD.Anz_init") .. "/ +:" .. obj(RCD_Name .. ".RCD.AnzOK"));
                  	else
                  	  --[[ alles OK: Statistik hochzählen ]]
                  	  set(RCD_Name .. ".RCD.AnzOK", obj(RCD_Name .. ".RCD.AnzOK") + 1);
                  	  set(RCD_Name .. ".RCD.Status.Txt","+:" .. obj(RCD_Name .. ".RCD.AnzOK") .. "/ -:" .. obj(RCD_Name .. ".RCD.Anz_init"));
                  	end
                    end
                  </action>
                  Gruß Peter und nochmals Danke für Deine Tipps!

                  Kommentar


                    #10
                    Hi Peter,

                    danke für das Feedback! Zu Deinem LUA-Script wollte ich Dir noch sagen, dass ich irgendwo gelesen habe, dass linknx threading-Probleme im Zusammenhang mit LUA hatte und deswegen actions, die LUA-Scripts enthalten, nur nacheinander ausgeführt werden. Wenn das wirklich so ist (ich bin mir nicht sicher, ob ich das damals richtig verstanden habe), dann ist ein sleep(10) eine schlechte Idee, da in der Zeit zwar linknx und alle "normalen" actions weiterlaufen, aber LUA ist für die Zeit blockiert. Besser ist da ein delay der action!
                    Ich bin mir nicht sicher, ob ich jetzt Gerüchte streue, weil ich die Quelle nicht mehr weiß, aber ich hab mich ne Zeit lang intensiv mit linknx beschäftigt und alles Mögliche zu dem Thema gelesen und weiß einfach nicht mehr, wo das stand. Ich hatte mir damals nur gemerkt: "Kein sleep in LUA".

                    Nur so als Tip,
                    Gruß, Waldemar

                    P.S.: Das mit eval stand auch "irgendwo", aber das hab ich dann mal ausprobiert und es verhält sich so, wie ich es beschrieben habe...
                    OpenKNX www.openknx.de

                    Kommentar


                      #11
                      Hallo Waldemar,

                      ich wollte das Zeitverhalten und Multi-Threading mal etwas genauer unter die Lupe nehmen. Habe 5 Rules definiert:
                      • Dauerfeuer: die schreibt alle 2 Sekunden auf 20 GA einen String
                      • Test Delay: alle 3 Sekunden zunächst 10 GA, dann 5 Sek. Delay, dann nochmals 10 GA
                      • Test Sleep: alle 4 Sekunden zunächst 10 GA, dann 5 Sek. Sleep, dann nochmals 10 GA
                      • Test Script: alle 4 Sekunden (alles per Script in einer gemeinsamen action) 10 GA, dann 5 Sek. Sleep, dann 10 GA
                      • CheckLight: hier reagiere ich auf das Ein- und Ausschalten des Lichts, was ich etwa einmal pro Sekunde gemacht habe, um zu sehen, ob irgendwelche Aktionen dadurch unterbrochen werden.


                      Ergebnis:
                      • Dauerfeuer: wird durch CheckLight unterbrochen, wenn das Licht geschaltet wird
                      • Test Delay: nur die action, die das Delay enthält wartet 5 Sekunden bevor sie ausgeführt wird. Die nachfolgenden actions warten nicht! CheckLight unterbricht.
                      • Test Sleep: Die actions nach der Script-Action mit dem Sleep werden sofort ausgeführt, nach 5 Sek Wartezeit wird die Script-action mit dem Sleep fortgeführt. CheckLight unterbricht
                      • Test Script: Hier sehen wir eine saubere Ablaufsteuerung, weil alles in einem Script geschieht: 10 GA werden geschrieben, dann wird 5 Sek. gewartet, dann werden 10 GA geschrieben. In der Zwischenzeit startet das Script erneut, weil es ja alle 4 Sekunden gestartet wird. CheckLight unterbricht.


                      Fazit: kein Unterschied ersichtlich zwischen Delay und Sleep. Wenn man jedoch einen Ablauf so erstellen will, dass mehrere Aktionen nach einer definierten Wartezeit anlaufen, dann erscheint es mir transparenter, wenn alle Aktionen innerhalb eines Scripts stattfinden und die Wartezeit mit Sleep erfolgt.

                      LUA ist übrigens zu keiner Zeit blockiert, auch nicht während Test Script. Denn ich habe in jeder Rule Kontrollausgaben per Script eingebaut, die mir z.B. anzeigen, wann ein Delay oder ein Sleep startet und endet. Sieht ganz lustig aus, wenn eine actionlist schon seit 5 Sek komplett abgearbeitet ist und dann kommt die Meldung "Delay Stopp", die zu dieser actionlist gehört :-)

                      Gruß
                      Peter

                      Kommentar


                        #12
                        Hi Peter,

                        danke für die Info und für den Test - dann hab ich das wohl wirklich damals missverstanden. Dann kann ich die Bedenken wegen sleep und LUA vergessen.

                        Gruß, Waldemar
                        OpenKNX www.openknx.de

                        Kommentar


                          #13
                          Hallo Waldemar,

                          nachdem ich schon so viele Tipps von den Forums-Mitgliedern und auch offline-Hilfe, z.B. bei der Installation meines Raspi, bekommen habe, freue ich mich, wenn ich auch mal eine Kleinigkeit beitragen kann :-)

                          Gruß
                          Peter

                          Kommentar

                          Lädt...
                          X