Ankündigung

Einklappen
Keine Ankündigung bisher.

StatusBit für eine Aktive Szene - ein lernfähiges Makro

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

    StatusBit für eine Aktive Szene - ein lernfähiges Makro

    Für einen Kunden haben wir folgendes Makro geschrieben:
    Es soll erkennen, ob eine Szene aktiv ist, also alle in der Szene hinterlegten Gruppenadressen den abgelegten Status haben. Falls dem so ist, soll eine 1-Bit Adresse auf EIN gehen, sonst AUS.

    Dabei kann aber muss nicht der EibPC der Szenenaktor sein, d.h. das Makro ist unabhängig vom Szenenaktor. Das Makro soll lernfähig sein, d.h. die beteiligten Gruppenadressen im Szenenaktor sollen nicht parametriert werden müssen.

    Anbei das Makro hierzu.
    Der Aufruf erfolgt in der Form, wobei festegelegt wird, dass der Szenenaktor die Phy. Adresse 1.2.44 hat, die Szene vier GAs beteiligt hat und im Flash die Plätze 440 und 441 belegt werden.

    SzenenErkenner(MeineSz,"Sz-0/1/1",SzNr,4,1.2.44,"Status-0/1/3,EIN,440,441)

    Es wird demnächst in der EnertexScene.lib zu finden sein.
    Code:
    // @date    15.07.2014
    // @version    1 
    // @author    Dr.-Ing. M. Schuster  Enertex Bayern GmbH
    :begin SzenenErkenner(SzeneName,SzeneGA,SzeneNr,AnzahlGAs,AdresseAktor,StatusBitGA,Autoload,Speicherplatz1, Speicherplatz2)
    :info $Dieses Makro erkennt selbstständig, ob eine Szene aktiv ist. Es lernt die Szene beim Speichern automatisch mit. Die gelernten Daten werden in zwei Speicherplätzen im Flash gespeichert. Bei einem Neustart werden die Daten aus dem Flash, falls vorhanden, neu geladen. Der Status der in der Szene aktiven GAs wird beim Starten des EibPCs mit Lesetelegrammen abgefragt. Wenn die Szene nocht nicht gelernt wurde und noch nicht gespeichert wurde, so kann per Argument Autoload einmalig die Szene erneut gespeichert werden. Damit lernt das Makro die im Szenenaktor gespeicherten Gruppenadressen und deren Werte. Wenn die Szene aktiv ist, d.h. alle Gruppenadressen den in der Szene gespeicherten Wert annehmen, so wird ein 1-Bit Telegramm geschrieben (EIN für aktiv). Falls sich ein Wert einer beteiligten Gruppenadresse ändert, so wird ein AUS-Telegramm geschrieben. Das Makro wird per Zufallszahl innerhalb der ersten Verarbeitungsminute initialisiert. An der Szene können bis zu 64 Gruppenadressen aktiv sein.$\\
          $Ein eindeutiger Name für den Szenenerkennern, z.B. SzeneEssen.$\\
          $Die Gruppenadresse, über die die Szene im Szenenaktor aufgerufen wird.$\\
          $Die Szenennummer der Gruppenadresse$\\
          $Die Anzahl der beteiligten Gruppenadressen in dieser Szene (max. 64)$\\
          $Die phy. Adresse des Szenenaktors, z.B. 1.2.43. Sollte der EibPC der Szenenaktor sein, so muss hier 0.0.0 stehen.$\\
          $Die Statusgruppenadresse, auf die ein EIN gesendet wird, wenn alle Gruppenadressen auf dem Wert der Szene stehen.$\\
          $Wenn die Szene bei erstmaligen Start des Makros eingelernt werden soll, so löst der EibPC die Szene und das Abspeichern der Szene automatisch aus. Hier muss hier EIN stehen, ansonsten AUS.$\\
          $Das Makro benötigt zwei Speicherplätze im Flash (Zahl von 0 bis 999).$\\
          $Das Makro benötigt zwei Speicherplätze im Flash (Zahl von 0 bis 999) ungleich des Speicherplatzes 1.$
    :shortinfo: $Lernfähiger Szenerkenner für Statusbits$
    // Variables for readrawknx
    SzeneName_Kontroll=0
    SzeneName_Sender=0.0.0
    SzeneName_GA=0u16
    SzeneName_IsGa=AUS
    SzeneName_RoutingCnt=0
    SzeneName_Len=0
    SzeneName_NrGA=AnzahlGAs
    
    // Every Bit is an active GA (Bitmask) in CRC: If all bits (len) are set, the GA is 
    // active 
    SzeneName_CRC=0u64
    // CRC to compare
    SzeneName_CRCActive=shift(1u64,convert(SzeneName_NrGA,0s08))-1u64
    
    SzeneName_Active=AUS
    SzeneName_Type=1
    SzeneName_Val=0u32
    SzeneName_ValOrg=0u32
    // We need only 400 Bytes, as there are maximum 64 GAs monitored
    // all data is converted to u32
    SzeneName_Store=$$c400
    SzeneName_GAs=$$c400
    SzeneName_Data=$$c400
    SzeneName_ID=0u16
    SzeneName_GAAutoread=0u16
    SzeneName_GALoad=0
    SzeneName_Next=AUS
    // Check, if the scene is called to be stored
    SzeneName_SzeneRecord=AUS
    SzeneName_SzeneNrCount=0
    SzeneName_Clear=AUS
    
    // an "storescene" occurs: Start recording
    if event(SzeneGA) and SzeneGA==128+SzeneNr then {
       SzeneName_SzeneRecord=EIN;
       SzeneName_SzeneNrCount=0;
       SzeneName_GALoad=0;
       // Delete an old monitor, if already stored, as a new is initiated
       SzeneName_GAs=$$;
    } endif
    
    if after(SzeneName_GALoad==2, 10000u64)  then {
       callscene(SzeneGA,SzeneNr) 
    }endif
    
    if after(SzeneName_GALoad==2, 40000u64) then {
       storescene(SzeneGA,SzeneNr)
    }endif
    
    
    // Clear the whole buffer
    if SzeneName_Clear then {
       SzeneName_GAs=$$;
       SzeneName_Data=$$;
       SzeneName_Clear=AUS;
       SzeneName_Active=AUS;
       writeflash(SzeneName_Store,Speicherplatz1^u16);
       writeflash(SzeneName_GAs,Speicherplatz2^u16);
    } endif
    
    // Read the flash
    if after(systemstart(),convert(random(30000u32),0u64)) then {
        if  !SzeneName_SzeneRecord then {
           readflash(SzeneName_Store,Speicherplatz1^u16); 
           readflash(SzeneName_GAs,Speicherplatz2^u16); 
        } endif
    } endif 
    
    // Check if there are "old" scene are already stored in the past and
    // these are to be reloaded
    if after(systemstart(),convert(random(30000u32),0u64)+30000u64) then {
        SzeneName_SzeneNrCount=0;
        // Only read from flash, if nothing is already running
        if size(SzeneName_GAs)>0u16 and !SzeneName_SzeneRecord then {
             SzeneName_Next=!SzeneName_Next; 
             SzeneName_SzeneRecord=EIN;
             SzeneName_GALoad=1;
        } else {
             if Autoload then SzeneName_GALoad=2 endif;
       } endif
    } endif
    
    // Initialize the read sequences after an reload of the GAs
    if after(change(SzeneName_Next),250u64) then {
        SzeneName_GAAutoread=convert(split(SzeneName_GAs, convert(SzeneName_SzeneNrCount,0u16)*6u16 , convert(SzeneName_SzeneNrCount,0u16)*6u16 +5u16),0u16);
        if (SzeneName_SzeneNrCount < SzeneName_NrGA) and SzeneName_GAAutoread!=0u16 then {
             read(address(SzeneName_GAAutoread));
             SzeneName_SzeneNrCount=SzeneName_SzeneNrCount+1;
             SzeneName_Next=!SzeneName_Next;
        } endif;
    } endif 
    // If an scenes learns 
    if event(readrawknx(SzeneName_Kontroll,SzeneName_Sender,SzeneName_GA,SzeneName_IsGa,SzeneName_RoutingCnt,SzeneName_Len,SzeneName_Data)) and SzeneName_IsGa then {
        // Second Bytes contains 
            // Bit 7 = 1   => write
            // Bit 6 = 1   => writeresponse
            // Bit 7/6 = 0 => read
        SzeneName_Type=stringcast(SzeneName_Data,0u08,1u16) and 0xC0;
        //------------------------------------------------------------------
        // Check if an GA is to be monitored
        if !SzeneName_SzeneRecord and (SzeneName_Type==128) then 
        {
            SzeneName_ID=find(SzeneName_GAs, stringformat(SzeneName_GA,0,3,5,0)+$@$,0u16);
            if SzeneName_ID!=EOS then 
                {
                     SzeneName_Val=stringcast(SzeneName_Store,0u32,SzeneName_ID);
                     if SzeneName_Len==1 then {
                       SzeneName_ValOrg=convert(stringcast(SzeneName_Data,0u08,1u16) and 0x3F,0u32);
                     } else {
                SzeneName_ValOrg=stringcast(SzeneName_Data,0u32,2u16) ;
                     } endif ;
                 if SzeneName_Val==SzeneName_ValOrg then {
                    // Set the bit in CRC, if the value is the same
                         SzeneName_CRC=SzeneName_CRC or shift(1u64,convert((SzeneName_ID)/6u16,0s08));
                     } else {
                // Unset the bit in CRC, if the value is the same
                SzeneName_CRC=SzeneName_CRC and !shift(1u64,convert((SzeneName_ID)/6u16,0s08));
             } endif;
             if SzeneName_CRC== SzeneName_CRCActive then {
                SzeneName_Active=EIN;    
                     } else SzeneName_Active=AUS endif;
                } endif;
        } endif;
    
    
        //------------------------------------------------------------------
        //read Telegramm for a certain GA 
        if (SzeneName_Type==0) and SzeneName_SzeneRecord  and SzeneName_Sender==AdresseAktor and SzeneName_GALoad==0 then {
            SzeneName_GAs=SzeneName_GAs+stringformat(SzeneName_GA,0,3,5,0) +$@$;
            SzeneName_SzeneNrCount=SzeneName_SzeneNrCount+1;
            } endif;
        
        //------------------------------------------------------------------
        // The answers must be stored
        // but there was a read before the 
        if (SzeneName_Type==64) and SzeneName_SzeneRecord then {
            SzeneName_ID=find(SzeneName_GAs, stringformat(SzeneName_GA,0,3,5,0)+$@$,0u16);
            if SzeneName_ID!=EOS then {
                    // Data can be found at Byte 2
                if SzeneName_Len==1 then {
                     stringset(SzeneName_Store,stringcast(SzeneName_Data,0,1u16)and 0x3F ,SzeneName_ID);
            } else {
                stringset(SzeneName_Store,stringcast(SzeneName_Data,0u32,2u16),SzeneName_ID);
            } endif;
                // End of recording
            if SzeneName_SzeneNrCount==SzeneName_NrGA then {
                    SzeneName_SzeneRecord=AUS;
                SzeneName_GALoad=0;
                writeflash(SzeneName_Store,Speicherplatz1^u16);
                writeflash(SzeneName_GAs,Speicherplatz2^u16);
                SzeneName_Active=EIN;
                } endif;
            } endif;
           } endif;
    
    } endif
    
    if SzeneName_Active then write(StatusBitGA,EIN) else write(StatusBitGA,AUS)  endif
    :end
    Viel Spaß damit!
    offizielles Supportforum für den Enertex® EibPC: https://knx-user-forum.de/eibpc/
    Enertex Produkte kaufen

    #2
    Super ! Genau das habe ich am Wochenede gesucht als ich meine ersten Szenen auch in die Visu eingebaut habe.

    Danke, Peter

    Kommentar


      #3
      Cooles Makro!

      Bei uns gilt eine Szene so lange als "aktiv" (ebenfalls per Status-Bit bzw. -GA) bis auf der Szenen-GA eine andere Nummer gesendet wird. Das deckt natürlich bei weitem nicht so viele Fälle ab wie euer Makro. Aber für uns (und möglicherweise einige andere) reicht das so - und braucht nur wenige Zeilen Code.

      Gruß,
      Jens.

      Kommentar


        #4
        Zitat von DerRenovator Beitrag anzeigen
        Cooles Makro!

        Bei uns gilt eine Szene so lange als "aktiv" (ebenfalls per Status-Bit bzw. -GA) bis auf der Szenen-GA eine andere Nummer gesendet wird. Das deckt natürlich bei weitem nicht so viele Fälle ab wie euer Makro. Aber für uns (und möglicherweise einige andere) reicht das so - und braucht nur wenige Zeilen Code.

        Gruß,
        Jens.
        Dann stell doch bitte dein KurzMakro auch ein
        MfG MrKnx

        Kommentar


          #5
          Kann ich machen:

          [highlight=epc]
          // StatusGA fuer eine Szene
          // @date 02.09.2013
          // @version 1
          // @author DerRenovator, knx-user-forum.de
          :begin SzeneStatus(InSzeneGA, InSzeneWert, OutSzeneStatusGA)
          :info $Dieses Makro liefert einen boolschen Status für eine Szene.$\\
          $GA auf der die Szenenauswahl empfangen wird (i.d.R. u08)$\\
          $Wert auf vorgenannter GA der die entscheidende Szene identifiziert (i.d.R. u08)$\\
          $GA auf die der Status der Szene geschrieben wird (b01, 1=Szene aktiv, 0=Szene nicht aktiv)$
          :shortinfo $Status-GA für Lichtszene$

          // Szene-Taste betaetigt -> Status-Flag setzen
          if event(InSzeneGA) and InSzeneGA==InSzeneWert then {
          // Status-GA senden - falls nicht schon aktiv
          if !OutSzeneStatusGA then write(OutSzeneStatusGA,EIN) endif;
          } endif;

          // Andere Szene gewaehlt -> Status-Flag zuruecksetzen
          if event(InSzeneGA) and InSzeneGA!=InSzeneWert then {
          if OutSzeneStatusGA then write(OutSzeneStatusGA,AUS) endif;
          } endif;
          :end
          [/highlight]

          Anmerkung 1: Ohne Gewähr, da ungetestet, da wir selber ein erweitertes Makro mit Sperre des PM und Nachlaufzeit verwenden.

          Anmerkung 2: Ich möchte betonen, dass ich in keiner Weise die Qualität und Notwendigkeit des eingangs vorgestellten Enertex-Makros anzweifeln möchte.
          Es gibt aber Fälle, in denen ich dieses hier für hinreichend halte.

          Gruß,
          Jens.

          Kommentar


            #6
            Zitat von DerRenovator Beitrag anzeigen
            Anmerkung 2: Ich möchte betonen, dass ich in keiner Weise die Qualität und Notwendigkeit des eingangs vorgestellten Enertex-Makros anzweifeln möchte.
            Das hat hier wohl keiner angezweifelt. Der Hauptunterschied zu unserem Makro liegt darin, dass die Szene per se erkannt wird, es muss da diese gar nicht aufgerufen werden. Wenn z.B. eine Szene aus zwei GAs besteht,
            GA1 : 30%
            GA2 : AUS
            dann würde, wenn der Anwender selbst die Lichter auf diese Werte drückt, das Makro die Szene erkennen, auch wenn die gar nicht ausgeführt wurde.
            offizielles Supportforum für den Enertex® EibPC: https://knx-user-forum.de/eibpc/
            Enertex Produkte kaufen

            Kommentar


              #7
              Das Makro finde ich Klasse, die Implementierung war auch mir bisher zu aufwändig.

              Meine bisherige Lösung ging nur in die Richtung, die aktuell ausgewählte Szene in der Anzeige zu "löschen", sowohl für die Visu, als auch für die LEDs an den Tasten.
              BR
              Marc

              Kommentar

              Lädt...
              X