Jump to content

Welcome to Smart Home Forum by FIBARO

Dear Guest,

 

as you can notice parts of Smart Home Forum by FIBARO is not available for you. You have to register in order to view all content and post in our community. Don't worry! Registration is a simple free process that requires minimal information for you to sign up. Become a part of of Smart Home Forum by FIBARO by creating an account.

 

As a member you can:

  •     Start new topics and reply to others
  •     Follow topics and users to get email updates
  •     Get your own profile page and make new friends
  •     Send personal messages
  •     ... and learn a lot about our system!

 

Regards,

Smart Home Forum by FIBARO Team


  • 0

Scene to keep other scenes from looping.


Question

Posted

Hello.

With few of my installations i've been using a bunch of Z-wave Da Vinci Wall Controller - Just basic use, scenes that pretty much come down to if button 1 on the wall panel is ON, turn this single switch ON etc.

The issue is that when i try making this work both ways (scenes that make both the single switch and the wall panel change eatchother's status) they tend to fall into loop of both devices continuosly switching between ON and OFF (especially when somebody presses them several times at once by mistake).

Is there any way to create a scene that would limit the frequency at which other scenes can be activated? Something like allowing the light scene to start only once in 5 seconds or something that would automatically stop the scene after its been activated more than 5 times in 5 seconds.

3 answers to this question

Recommended Posts

  • 0
Posted

The short answer is to create a block scene and when you are creating it there is an option Allow to restart a running scene: ?

 

If this is set to NO it will prohibit multiple scenes from starting. Then you  could put in a delay at the end of the scene to achieve that cooldown period you want.

 

Other ways exist such as using a lua script and either recording the event and looking for that recording before processing the next time. Or doing the same by looking at event history and parsing recent events for your switches. Or you could build similar functionality into a QuickApp. 

  • 0
  • Inquirer
  • Posted
    W dniu 20.04.2023 o 17:07, RedRocketFire napisał:

    Other ways exist such as using a lua script and either recording the event and looking for that recording before processing the next time. Or doing the same by looking at event history and parsing recent events for your switches. Or you could build similar functionality into a QuickApp. 

    Any chance you could provide an example? I have several instalation that uses HC2 gateways and this could be very useful for such cases.

    • 0
    Posted (edited)

    I made this on an HC3. I don't know if it will work on HC2. Its just a Proof Of Concept script.

    I can run this LUA scene and it will look into history and see if it ran recently. It will always find one record, the record of itself being launched. If it finds additional records it will not process any further. I have it set to a 10 second cooldown so it is easy to just play with it and see what is happening. It also outputs the API call so you can play with that by pasting it into a web  browser.

    I still think there may be better ways to achieve what is needed.

     

     
    print("--==========================================================================================")
    print("--BEGIN SCENE ==============================================================================")
    print("--==========================================================================================")
     
    -- determines if the scene has run recently or not based on our cooldown.
    function sceneCooldownComplete(thisSceneId, cooldownStartTime, executionTime, maximumRecords)
        print("function:sceneCooldownComplete")
        -- print("thisSceneId:"..thisSceneId)
        -- print("cooldownStartTime:"..cooldownStartTime)
        -- print("executionTime:"..executionTime)
        -- print("maximumRecords:"..maximumRecords)
        local cooldownComplete = true
        local lastExecutionTime = 0
        local excludedCurrentExecution = true
        
        lastSceneExecutionTime = getLastSceneExecutionTime(thisSceneId, cooldownStartTime, executionTime, maximumRecords, excludedCurrentExecution)
     
        if lastSceneExecutionTime > cooldownStartTime then
            cooldownComplete = false
        end
        
        print("cooldownComplete:"..tostring(cooldownComplete))
        return cooldownComplete
    end
     
    -- gets the last time the scene ran as queried from events history records based on api parmater values
    function getLastSceneExecutionTime(thisSceneId, cooldownStartTime, executionTime, maximumRecords, excludedCurrentExecution)
        print("function:getLastSceneExecution")
        -- print("thisSceneId:"..thisSceneId)
        -- print("cooldownStartTime:"..cooldownStartTime)
        -- print("executionTime:"..executionTime)
        -- print("maximumRecords:"..maximumRecords)
        -- print("excludedCurrentExecution:"..excludedCurrentExecution)
        local lastSceneExecutionTime = 0
     
        local sourceType = nil --"user"
        local objectType = "scene"
        local from = cooldownStartTime
        local to = executionTime
        local numberOfRecords = maximumRecords
     
        eventsHistoryObjects = getEventsHistoryObjects(sourceType, objectType, from, to, roomID, numberOfRecords)
     
        -- iterating, probably in reverse chronological order
        for _e, event in ipairs(eventsHistoryObjects) do
            -- example of events history scene data
            --[[
                {
                    "data":{"id":338,"startTime":1682512635,"subid":1,"trigger":null,"type":""},
                    "id":1546526,
                    "objects":[{"id":338,"type":"scene"}],
                    "sourceId":2,
                    "sourceType":"user",
                    "timestamp":1682512635,
                    "type":"SceneStartedEvent"
                }
            --]]
     
            print("-----------------------")
            print("examining record:".._e)
            print("-----------------------")
     
            -- capture the time and device id. we have already asserted that these are scenes
            local startTime = (event.data and event.data.startTime or 0)  
            local id = (event.data and event.data.id or 0)
            local type = (event.type or 0)
            print("startTime:"..startTime)
            print("readable time:"..os.date("%Y-%m-%d %X", startTime))
            print("id:"..id)
            print("name:"..api.get("/scenes/"..id).name)
            print("type:"..type)
     
            -- if this is a valid SceneStartedEvent return the startTime
            if startTime >= cooldownStartTime
            and startTime <= executionTime 
            and type == "SceneStartedEvent" then
                print("matching record discovered")
                if excludedCurrentExecution then
                    print("The parameter excludedCurrentExecution indicates we need to skip one matching record. Moving on.")
                    excludedCurrentExecution = false
                else
                    -- we only need the most recent qualified record.
                    
                    print("record accepted.")
                    lastSceneExecutionTime = startTime
                    break
                end
            else        
                print("non matching record ignored.")
            end
     
        end
            print("-----------------------")
            print("no more records")
            print("-----------------------")
     
        print("lastSceneExecutionTime:"..tostring(lastSceneExecutionTime))
        print("lastSceneExecutionTime:"..os.date("%Y-%m-%d %X", lastSceneExecutionTime))
        return lastSceneExecutionTime
    end
     
    -- gets events history records based on api parmater values
    function getEventsHistoryObjects(sourceType, objectType, from, to, roomID, numberOfRecords)
        print('function:getEventsHistoryObjects')
        
        -- just let us know know what variables we will work with
        local parameters = ""
        local eventsHistoryApiPath = "/events/history"
        local eventsHistoryObjects = nil
        
        -- if the parameter values are not nil append them as strings to the parameters for the api query
        if sourceType               then parameters = parameters.."&sourceType="..tostring(sourceType)                    end
        if objectType               then parameters = parameters.."&objectType="..tostring(objectType)                    end
        if from                     then parameters = parameters.."&from="..tostring(from)                                end
        if to                       then parameters = parameters.."&to="..tostring(to)                                    end
        if roomID                   then parameters = parameters.."&roomID="..tostring(roomID)                            end
        if numberOfRecords          then parameters = parameters.."&numberOfRecords="..tostring(numberOfRecords)          end
     
        --remove the leading "&"" since it is not needed on the first parameter
        parameters = parameters:sub(2)
        
        eventsHistoryApiPath = eventsHistoryApiPath.."?"..parameters
        print("eventsHistoryApiPath:"..eventsHistoryApiPath)
     
        -- get the api results
        eventsHistoryObjects = api.get(eventsHistoryApiPath)
     
        --return the collection
        return eventsHistoryObjects
    end
     
    --==================================================================
    --==================================================================
    --==================================================================
    print("begin execution")
     
    -- hard coded values
    local sceneCooldownSeconds = 10
    local maximumRecords = 100
    local thisSceneId = sceneId
    local executionTime = os.time()
    local cooldownStartTime = executionTime - sceneCooldownSeconds
     
    -- check events history for our scene's last execution
    if sceneCooldownComplete(thisSceneId, cooldownStartTime, executionTime, maximumRecords) then
        print("--!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
        print ("processing lighting commands")
        print("--!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
    else
        print("--!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
        print ("bypassing lighting commands")
        print("--!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
    end
     
    print("--==========================================================================================")
    print("--END SCENE ==============================================================================")
    print("--==========================================================================================")



     
     
    Edited by RedRocketFire

    Join the conversation

    You can post now and register later. If you have an account, sign in now to post with your account.

    Guest
    Answer this question...

    ×   Pasted as rich text.   Paste as plain text instead

      Only 75 emoji are allowed.

    ×   Your link has been automatically embedded.   Display as a link instead

    ×   Your previous content has been restored.   Clear editor

    ×   You cannot paste images directly. Upload or insert images from URL.

    ×
    ×
    • Create New...