Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Skripten / Logik
    4. JavaScript
    5. Konstantes Dimmen bei gedrückter Taste

    NEWS

    • Neuer Blog: Fotos und Eindrücke aus Solingen

    • ioBroker@Smart Living Forum Solingen, 14.06. - Agenda added

    • ioBroker goes Matter ... Matter Adapter in Stable

    Konstantes Dimmen bei gedrückter Taste

    This topic has been deleted. Only users with topic management privileges can see it.
    • Keromida
      Keromida last edited by Keromida

      Hallo zusammen!

      Ich bin hier leider nicht wirklich fündig geworden und benötige Hilfe bei der Programmierung einer kontinuierlichen Dimmfunktion solange eine Taste gedrückt bleibt. D.h. ich möchte gerne bei gedrückter Taste von 0 bis 100 variabel Dimmen können. Hierfür habe ich mir die Tradfri Dimmer gekauft, welche die Zustände 1001 (Aus, Taste wird gehalten), 1002 (Aus, Taste gedrückt), 1003 (Aus, Taste nach 1001 losgelassen), sowie das Pendent abgebildet auf 200X.

      Geplant war eigentlich das ganze in einem Switch/If-Statement den Tastenzustand abzufragen und über eine While-Schleife das ganze so lange laufen zu lassen bis entweder 100% bzw. 0% erreicht sind oder die Taste vorher losgelassen wird. Hierfür habe ich mir eine Funktion geschrieben, die das theoretisch können sollte.

      function setLevel(SwitchState){
          if(SwitchState == 1001){
              while(Level_Value <= 100){
                  Level_Value = getState("deconz.0.Lights.1.level").val + 1;
                  console.log(Level_Value);
                  setState("deconz.0.Lights.1.level", Level_Value);
              }
          }
          else{
              return;
          }
      }
      

      Die Funktion wird auch aufgerufen, jedoch ändert sich die Lichtintensität nicht. Lege ich das was innerhalb der While-Schleife liegt außerhalb hin, so wird der Wert um 1% erhöht. Das ganze stellt hier nur ein Example dar, da ich erst die Grundfunktionalität zum laufen kriegen will. Die Abfrage ob die Taste losgelassen wurde fehlt hier. Hat hier jemand einen Tipp woran es liegt? Besten Dank!

      Viele Grüße
      Keromida

      K paul53 Asgothian 3 Replies Last reply Reply Quote 0
      • K
        klassisch Most Active @Keromida last edited by klassisch

        @keromida Bei mir in etwa so:

        const s01Button1HoldId = oppleSwitch02 + '.' + 'button_'+ n +'_hold';
              const s01DimUp_buttonId = s01Button1HoldId; 
              on({id: s01Button1HoldId , change: "gt"}, function(obj){ dimUp_Button() });
        
        
         async function dimUp_Button() { 
            // dim up  
            if(debugLogOn) console.log('button dim up press ');
            // clearAllTimouts();
            bright = getState(lampBrightnessId ).val;
            lastLampBright = bright;
            let buttonHold = getState(s01DimUp_buttonId).val || getState(s02DimUp_buttonId).val;
            await delay (0.1);
            while((buttonHold) && (bright < maxBright)){
                if(debugLogOn) console.log('loop');
                bright = bright + deltaBright ;
                if (bright >= maxBright) bright = maxBright; //clipping
                if(debugLogOn) console.log ('bright ' + bright);
                setState(lampBrightnessId ,bright);
                lastLampBright = bright;
                buttonHold = getState(s01DimUp_buttonId).val || getState(s02DimUp_buttonId).val;
                await delay (0.2);
            }
        };
        

        Ikea Floalt als Panel; aqare Opple als Taster (2 Stck, s01 und s02) und ein CC2652P als Koordinator. Kein ikea GW.

        Im Übrigen gehen in dieser Konfiguration auch die ikea symfonisk Drehsteller recht gut. Bei Gruppen etwas schlechter

        1 Reply Last reply Reply Quote 0
        • paul53
          paul53 @Keromida last edited by paul53

          @keromida sagte: über eine While-Schleife das ganze so lange laufen zu lassen bis entweder 100% bzw. 0% erreicht sind oder die Taste vorher losgelassen wird.

          Verwende ein Intervall, das beim langen Drücken gestartet und beim Loslassen gestoppt wird. Beispiel:

          const idLevel = 'deconz.0.Lights.1.level';
          const idHeller = '...';
          const idDunkler = '...';
          
          var timer = null;
          
          function dimmen(delta) {
              let level = getState(idLevel).val;
              if(delta > 0 && level < 100 || delta < 0 && level > 0) {
                  timer = setInterval(function() {
                      level += delta;
                      setState(idLevel, level);
                      if(level <= 0 || level >= 100) clearInterval(timer);
                  }, 250);
              } 
          }
          
          on(idHeller, function(dp) {
              if(dp.state.val == 1001) dimmen(1);
              else if(dp.state.val == 1003) clearInterval(timer);
          });
          
          on(idDunkler, function(dp) {
              if(dp.state.val == 1001) dimmen(-1);
              else if(dp.state.val == 1003) clearInterval(timer);
          });
          
          OliverIO 1 Reply Last reply Reply Quote 1
          • OliverIO
            OliverIO @paul53 last edited by

            @paul53 sagte in Konstantes Dimmen bei gedrückter Taste:

            @keromida sagte: über eine While-Schleife das ganze so lange laufen zu lassen bis entweder 100% bzw. 0% erreicht sind oder die Taste vorher losgelassen wird.

            Verwende ein Intervall, das beim langen Drücken gestartet und beim Loslassen gestoppt wird.

            sollte man dazwischen evtl eine pause einbauen?
            die while schleife ist blitzeschnelle bei 100, so das man in real wahrscheinlich kein dimmen wahrnimmt, sondern das licht zack bei 100% ist.

            bei @klassisch sehe ich so ein delay

            paul53 1 Reply Last reply Reply Quote 1
            • paul53
              paul53 @OliverIO last edited by

              @oliverio sagte: sollte man dazwischen evtl eine pause einbauen?

              Das Intervall macht diese Pause.

              1 Reply Last reply Reply Quote 1
              • Keromida
                Keromida last edited by Keromida

                Danke für eure Antworten! Mein Fehler war tatsächlich schlicht und ergreifend, dass ich keinen Delay gesetzt habe für die Übertragung der Telegramme. Dadurch wurde der Übergang nicht gesetzt. Danke für die Hilfe! Hier der vollständige Code.

                /*
                The code makes the use of the IKEA tradfri dimmer switch to adjust a group of lights over a data point or just a single lamp.
                */
                
                const id_ButtonEvent            = 'deconz.0.Sensors.4.buttonevent';     // Input Button Event Data Point
                const id_LampBrightnessLevel    = 'deconz.0.Lights.1.level';            // Input Level Data Point
                const id_LampOnState            = 'deconz.0.Lights.1.on';               // Input OnState Data Point
                const max_Brightness            = 100;  // refers to 100%
                const min_Brightness            = 0;    // Refers to 0%
                const delta_Brightness          = 5;    // in percent
                const setBrightnessValue_Delay  = 250;  // in miliseconds, sets the periodic adjustment of the brightness level
                
                let setBrightnessValue = null;
                
                function setLampStates(delta_BrightnessValue){
                    let Level_Value = getState(id_LampBrightnessLevel).val;
                    if((delta_BrightnessValue >= min_Brightness && Level_Value <= max_Brightness) || (delta_BrightnessValue <= 0 && Level_Value >= 0)) {
                        setBrightnessValue = setInterval(function() {
                            Level_Value = Level_Value + delta_BrightnessValue;
                            setState(id_LampBrightnessLevel, Level_Value);
                            if(Level_Value <= 0 || Level_Value >= 100){
                                clearInterval(setBrightnessValue);
                            }
                        }, setBrightnessValue_Delay);
                    } 
                }
                
                on({id: id_ButtonEvent}, async function(obj){
                    switch(getState(id_ButtonEvent).val){
                        case 1001:{
                            setLampStates(delta_Brightness);
                            break;
                        }
                        case 1002:{
                            setState(id_LampOnState, true);
                            break;
                        }
                        case 1003:{
                            clearInterval(setBrightnessValue);
                            break;
                        }
                        case 2001:{
                            setLampStates(-delta_Brightness);
                            break;
                        }
                        case 2002:{
                            setState(id_LampOnState, false);
                            break;
                        }
                        case 2003:{
                            clearInterval(setBrightnessValue);
                            break;
                        }
                    }
                    
                });
                
                1 Reply Last reply Reply Quote 0
                • Asgothian
                  Asgothian Developer @Keromida last edited by Asgothian

                  @keromida sagte in Konstantes Dimmen bei gedrückter Taste:

                  Die Funktion wird auch aufgerufen, jedoch ändert sich die Lichtintensität nicht. Lege ich das was innerhalb der While-Schleife liegt außerhalb hin, so wird der Wert um 1% erhöht. Das ganze stellt hier nur ein Example dar, da ich erst die Grundfunktionalität zum laufen kriegen will.

                  Diese Art von schleifen funktionieren prinzipiell nicht.

                  Grund dafür ist das der ioBroker asynchron arbeitet. Einige Funktionen (in deinem Beispiel die "setState") Funktion kehren zurück bevor die eigentliche Aktion ausgeführt ist. Das Ausführen kann dann noch wenige ms dauern (manchmal auch wenige 10 ms).

                  Dadurch wird in deiner While Schleifer der Helligkeitswert wahrscheinlich nie erhöht werden. Du kannst zur Vereinfachung davon ausgehen das

                  • der Befehl setState in Umgangssprache als Merke den Folgenden Wert zur Änderung auf den angegebenen Wert vor ausgedrückt werden kann
                  • das diese vorgemerkte Änderung effektiv erst passiert wenn Dein Skript abgearbeitet (oder angehalten) ist (z.bsp via den "Pause" Block
                  • das While/for/repeat schleifen in < 1 ms durchlaufen können.

                  Wenn Du diesen Annahmen Folgst sollte klar sein das letztendlich der Wert Level_Value nie über getState("deconz.0.Lights.1.level").val + 1 hinaus kommt.

                  Die "best practice" Methode für diese Art Aufgaben hat @paul53 bereits vorgestellt, da gibt es wenig zu ergänzen. Sie ist auch einem Konstrukt mit

                  While (a) {
                    do something
                    pause(250);
                  }
                  

                  vorzuziehen.

                  Du wirst auf Dauer nicht darum herum kommen dich mit timeout und intervall auseinander zu setzen. Die Klassischen "while" schleifen sind für komplexe Aufgaben oft nicht flexibel genug und verleiten dazu zyklisch irgendwelche Werte abzufragen um eine Abbruchbedingung zu bekommen an Statt diese Aufgabe dem ioBroker zu überlassen und die Aktion über einen Trigger zu beenden.

                  A.

                  Keromida 1 Reply Last reply Reply Quote 1
                  • Keromida
                    Keromida @Asgothian last edited by

                    @asgothian Danke für die sehr ausführliche und verständliche Antwort! Das bringt jetzt auch eindeutig Licht ins Dunkel wieso mein Code nicht geklappt hat.

                    1 Reply Last reply Reply Quote 0
                    • First post
                      Last post

                    Support us

                    ioBroker
                    Community Adapters
                    Donate

                    463
                    Online

                    31.9k
                    Users

                    80.1k
                    Topics

                    1.3m
                    Posts

                    5
                    8
                    552
                    Loading More Posts
                    • Oldest to Newest
                    • Newest to Oldest
                    • Most Votes
                    Reply
                    • Reply as topic
                    Log in to reply
                    Community
                    Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
                    The ioBroker Community 2014-2023
                    logo