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


Recommended Posts

  • Topic Author
  • Posted (edited)

    logical expressions in ||>> works well

    Please login or register to see this code.

    what specific problems do you have?

     

    What you want to do is trigger a rule when something doesn't match - when it doesn't match 924,927,1384,2386... and the general problem of doing "not match" in the header part is tricky - for integers like in this case it's doable, but for other arbitrary expressions it's difficult. I propose 2 ways you can solve it with the current mechanisms.

    Please login or register to see this code.

    which is similar to your second example, and very efficient.

    You could also define your own lua member function (there is no member function in ER) and use that

    Please login or register to see this code.

    but the earlier table map is more efficient as it is a direct lookup.

     

    A side note here. 'exceptDevices' must be a global Lua variable for the variable to be accessible inside the rules. 

    However, we can declare our value as a rule variable to avoid having global variables in our code.

    Please login or register to see this code.

     

    The other approach is to leverage the rule matching mechanism. Rules are matched from first rule (top) to last rule (bottom) and all rules that match are executed.

    However,  a rule can stop the matching of the rules coming after by returning a "magical" value. 

    If we run

    Please login or register to see this code.

    it will log 'A' and 'B' as expected.

    If we run 

    Please login or register to see this code.

    The value returned by a rule is the last value, and if we return the magical value fibaro.EM.BREAK it will stop matching rules after

    - and it will only log 'A'

     

    So, this can be used in your case by having a first rule that matches to your exception devices and do nothing and breaks, and a second rule that matches to your other devices and carries out the action.

    Please login or register to see this code.

    The order of the rules are of course important here.

    We also use another feature that is that the #device event is the only event that allows the id key to be a list if integers and it will match if any of the integers in the list match the deviceId. It's a special hack for #device for convenience... it is equivalent to writing

    Please login or register to see this code.

    ...just shorter (the compiler actually transforms the former to the latter)

    Edited by jgab
    Posted (edited)
    4 hours ago, jgab said:

    logical expressions in ||>> works well

    Please login or register to see this code.

    what specific problems do you have?

     

    What you want to do is trigger a rule when something doesn't match - when it doesn't match 924,927,1384,2386... and the general problem of doing "not match" in the header part is tricky - for integers like in this case it's doable, but for other arbitrary expressions it's difficult. I propose 2 ways you can solve it with the current mechanisms.

    Please login or register to see this code.

    which is similar to your second example, and very efficient.

    You could also define your own lua member function (there is no member function in ER) and use that

    Please login or register to see this code.

    but the earlier table map is more efficient as it is a direct lookup.

     

    A side note here. 'exceptDevices' must be a global Lua variable for the variable to be accessible inside the rules. 

    However, we can declare our value as a rule variable to avoid having global variables in our code.

    Please login or register to see this code.

     

    The other approach is to leverage the rule matching mechanism. Rules are matched from first rule (top) to last rule (bottom) and all rules that match are executed.

    However,  a rule can stop the matching of the rules coming after by returning a "magical" value. 

    If we run

    Please login or register to see this code.

    it will log 'A' and 'B' as expected.

    If we run 

    Please login or register to see this code.

    The value returned by a rule is the last value, and if we return the magical value fibaro.EM.BREAK it will stop matching rules after

    - and it will only log 'A'

     

    So, this can be used in your case by having a first rule that matches to your exception devices and do nothing and breaks, and a second rule that matches to your other devices and carries out the action.

    Please login or register to see this code.

    The order of the rules are of course important here.

    We also use another feature that is that the #device event is the only event that allows the id key to be a list if integers and it will match if any of the integers in the list match the deviceId. It's a special hack for #device for convenience... it is equivalent to writing

    Please login or register to see this code.

    ...just shorter (the compiler actually transforms the former to the latter)

    Please login or register to see this code.

    Thank you Jan

    Edited by Neo Andersson
  • Topic Author
  • Posted (edited)

    Well, the 

    Please login or register to see this code.

    is just a way to immediately run a dummy rule. $X is nil as X is not a global fibaro variable (for me), and !<expr> is the logical not of nil which is true.

    So the rule is always true. However, rules only run when they are triggered and X is not set anywhere, so instead we run the rule at definition by adding .start().

    The rule will run immediately, and !$X is true and the action is executed.

     

    Yes, you could also have declared the exceptDevices in the HT table.

     

    Util.defvar only declares a local ER variable. Util.defvars is just a version that declares a table of many variables and is used for the HT setup. Util.defvars calls Util.defvar repeatedly...

     

    Util.defTriggerVar also declares a local ER variable, but with the difference that it will trigger rules if it changes value, and we can thus use it in the header of the rule.

    Like 'T' trigger the rules in the example above when we change the value to true (variables start out with nil as value if we don't give them initial values)

    triggerVars only triggers rules they appear in when their value changes to something new, so setting 'T' to true multiple times will not re-trigger the rule.

     

    There are no more interesting Util functions except Util.reverseMapDef that is used to allow the log functions to log the name of a device instead of just the deviceId...

    Edited by jgab
    Posted
    14 minutes ago, jgab said:

    Well, the 

    Please login or register to see this code.

    is just a way to immediately run a dummy rule. $X is nil as X is not a global fibaro variable (for me), and !<expr> is the logical not of nil which is true.

    So the rule is always true. However, rules only run when they are triggered and X is not set anywhere, so instead we run the rule at definition by adding .start().

    The rule will run immediately, and !$X is true and the action is executed.

     

    Yes, you could also have declared the exceptDevices in the HT table.

     

    Util.defvar only declares a local ER variable. Util.defvars is just a version that declares a table of many variables and is used for the HT setup. Util.defvars calls Util.defvar repeatedly...

     

    Util.defTriggerVar also declares a local ER variable, but with the difference that it will trigger rules if it changes value, and we can thus use it in the header of the rule.

    Like 'T' trigger the rules in the example above when we change the value to true (variables start out with nil as value if we don't give them initial values)

    triggerVars only triggers rules they appear in when their value changes to something new, so setting 'T' to true multiple times will not retriever the rule.

     

    There are no more interesting Util functions except Util.reverseMapDef that is used to allow the log functions to log the name of a device instead of just the deviceId...

    Okay, and please can you explain this part for me?


     

    Please login or register to see this code.

     

  • Topic Author
  • Posted
    12 minutes ago, Neo Andersson said:

    Okay, and please can you explain this part for me?


     

    Please login or register to see this code.

     


    it’s just a normal lua table lookup with the id as key returning the associated Boolean value.

  • Topic Author
  • Posted
    22 minutes ago, jgab said:


    it’s just a normal lua table lookup with the id as key returning the associated Boolean value.

    ..and then a logical not to return true if the is is not in the table

    • Like 1
    Posted

    @jgabJan, i have to bother you again, because something that used to work in a block scene doesn't seem to work using ER4.

    Here is the task: User has a Door Lock a Door sensor and a Gate sensor. He wanted us to unlock his door automatically, when he opens the gate, so he arrived home.

    So we had to determine somehow, that he is coming home and not leaving. Thats why we used to check, if he's door sensor is safe more than 15 minutes, that means, he is just arriving and not leaving, (otherwise his door sensor would have been breached when he left the house.)

     

    So we used to do it in a scene where when gate sensor gets breached and the door sensor is safe more than 15 minutes, we unlock the door for him. This used to work pretty well. Not a very secure way but he agreed to do it this way.

     

    Now we have created a rule for it, which doesn't work

     

    Please login or register to see this code.

     

    However this doesn't work. I suppose because the trueFor cycle is starting its counter only at the moment when the gate got breached.
    The goal is, whenever  the gate got breached, and the door sensor was safe for minimum 15 minutes, we can unlock the door.
    How to format the rule to achieve this functionality?
    I have some idea in my head, that we can use the trueFor part in a separate rule and set a global variable to store a flag
    Is there any more elegant solution without using global variable?

     

  • Topic Author
  • Posted (edited)
    1 hour ago, Neo Andersson said:

    So we used to do it in a scene where when gate sensor gets breached and the door sensor is safe more than 15 minutes, we unlock the door for him. This used to work pretty well. Not a very secure way but he agreed to do it this way.

     

    Now we have created a rule for it, which doesn't work

     

    Please login or register to see this code.

     

     

    Well, the problem here is that using trueFor you want something to happen after the door being closed for 15min. But here it's just a condition. You just want to check if the door has been closed at least 15min when the gate is opened

    This would work

    Please login or register to see this code.

    device:last returns the number of seconds since the device changed state the last time. Most devices support that but not all- A door sensor should support that.

    (It's the second value returned by fibaro.getValue(id,"value") subtracted from the current time).

    Edited by jgab
    Posted (edited)
    16 hours ago, jgab said:

     

    Well, the problem here is that using trueFor you want something to happen after the door being closed for 15min. But here it's just a condition. You just want to check if the door has been closed at least 15min when the gate is opened

    This would work

    Please login or register to see this code.

    device:last returns the number of seconds since the device changed state the last time. Most devices support that but not all- A door sensor should support that.

    (It's the second value returned by fibaro.getValue(id,"value") subtracted from the current time).

    Wou, thats cool..I never heard about the last property. How do i know, if device supports it? Is it something that can be checked in swagger or where is this property coming from?  If it exists, Is it a device's standard inbuilt feature?

    UPDATE: I have chcked and found something like lastBreached..I think that should be it. I think this is supported probably for sensor type devices. Thanks you Jan.

    Edited by Neo Andersson
    Posted
    42 minutes ago, Neo Andersson said:

    Wou, thats cool..I never heard about the last property. How do i know, if device supports it? Is it something that can be checked in swagger or where is this property coming from?  If it exists, Is it a device's standard inbuilt feature?

    UPDATE: I have chcked and found something like lastBreached..I think that should be it. I think this is supported probably for sensor type devices. Thanks you Jan.

    Just in case anyone else is interested. I have noticed that linked sensors don't report this value, even if they have this property in swagger, it never gets updated. I will ask FIbaro about this in a support ticket.

    Posted

    @jgab Hello Jan. Is it possible to get back the counter status from a trueFor cycle somehow? If i want to log the remaining seconds of a trueFor loop? I can do some loops formyself, but i was thinking, that a trueFor cycle is doing his loop anyway, so itis in vain to start another loop the see the counter states. I believe trueFor is looping with 1 sec interval, so is there some way to get back the counter status?

  • Topic Author
  • Posted

    lastBreached is, I guess, when it was last breached, not changed. The property I use in :last is whenever the value property changes. to safe or to breached. Most switches, sensors etc support that.

     

    What you could do is keep track of it yourself.

    Please login or register to see this code.

     

  • Topic Author
  • Posted
    46 minutes ago, Neo Andersson said:

    @jgab Hello Jan. Is it possible to get back the counter status from a trueFor cycle somehow? If i want to log the remaining seconds of a trueFor loop? I can do some loops formyself, but i was thinking, that a trueFor cycle is doing his loop anyway, so itis in vain to start another loop the see the counter states. I believe trueFor is looping with 1 sec interval, so is there some way to get back the counter status?

    Actually, there is no timer. It just sets a setTimeout waiting for the time and meanwhile monitors if the rules get triggered and the condition changes.

    It's different from fibaroExtra's trueFor that needs to poll the condition every x second. Here we instead wait for the rule to get triggered.... more efficient.

     

    There are events posted when the trueFor starts and stops but they are not so user-friendly to deal with

    Ex.

    Please login or register to see this code.

    There is an event posted #trueFor{rule=<rule>, start=true} when the trueFor starts waiting and 

    #trueFor{rule=<rule>, stop=true, expired<boolean>} when the trueFor stops waiting. expired is true if the rule will run and nil if the rule was cancelled.

     

    So, there is no time you can count down with. 

     

    It is possible to solve with some (advanced) rules though

    Please login or register to see this code.

    Here we save the time in 'ruleTime' in the first rule.

    When the trueFor starts, we start to count down with another rule

    Note, that if the trueFor stops (cancelled or expired) we kill the counting down rule.

  • Topic Author
  • Posted (edited)

    You could of course also call your own Lua function to start stop a counter

     

    Please login or register to see this code.

     

    Edited by jgab
  • Topic Author
  • Posted
    5 minutes ago, jgab said:

    You could of course also call your own Lua function to start stop a counter

     

    Please login or register to see this code.

     

     

    I may change the #trueFor event in next release and make it more informative - including time.

    Posted
    11 minutes ago, jgab said:

     

    I may change the #trueFor event in next release and make it more informative - including time.

    Thanks, that would be nice

    Posted (edited)

    @jgab Jan,

    Please login or register to see this code.

    or

     

    Please login or register to see this code.

     

    should be used if checking value of a global var?

     

    and what if i have stored a boolean string? Will ER4 convert it to boolean

     

    Please login or register to see this code.

     

    so will it be checked against 'true' as string or true as boolean

     

    Thanks

     

     

    Edited by Neo Andersson
  • Topic Author
  • Posted (edited)

    strings in ER are always with quotes, so

    Please login or register to see this code.

     

    If the global var contains 'true','True','TRUE',false','False','FALSE' it will be returned as a boolean so you test

    Please login or register to see this code.

     

    if the global var contains a number the number returned

    if the global var contains a json encoded table the table will be returned

     if the global var contains a string with a valid time format ex. "00:10",  a number representing the seconds will be returned (here 10*60 = 600)

     

    So this works in ER

    Please login or register to see this code.

     

    Edited by jgab
    • Like 1
    Posted

    @jgab can you help with this change? 

    I'm trying to setup on specific dates and time over the week different types of veriables. I would like to also change profile along with such operation.

    rule("@sunrise-00:10 & wday('sat-sun') => $DayTime='Morning'") + change a profile to: xxx
  • Topic Author
  • Posted
    11 hours ago, dairogue said:

    @jgab can you help with this change? 

    I'm trying to setup on specific dates and time over the week different types of veriables. I would like to also change profile along with such operation.

    rule("@sunrise-00:10 & wday('sat-sun') => $DayTime='Morning'") + change a profile to: xxx

     

    Please login or register to see this code.

    QA:activeProfile can take the name or the ID of the profile as the argument.

    Join the conversation

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

    Guest
    Reply to this topic...

    ×   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...