Jump to content
Guides for the Forum Read more... ×
Poradniki na Forum Read more... ×

Recommended Posts

  • Topic Author
  • 7 minutes ago, petrkl12 said:

    I think this will change label for lblButtonID to value 4003 but I need test value not change it ...

    Rule.eval("#property{deviceID=860} => label(860,'lblButtonID')=='4003' & log('Button Off 1')")
     

    this rule is without reaction as you can see in log

    Rule.eval("#property{deviceID=860} => || label(860,'lblButtonID')=='4003' >> log('Button Off 1')")

     

    The first is doing comparison '==' not assignment '=', so it shouldn't change the label.

    The second one is different from your third rule; "<event> => || <test> >> <action>"

    Edited by jgab

    Share this post


    Link to post
    Share on other sites

    OK, first is working :)  Thanks - logic is not so easy :)

    second I will try tommorow

     

    Share this post


    Link to post
    Share on other sites
  • Topic Author
  • 1 minute ago, petrkl12 said:

    OK, first is working :)  Thanks - logic is not so easy :)

    second I will try tommorow

     

    The second syntax "|| >>" is a bit tricky. But it would allow you to do things like this (I don't know what codes your device returns).

    Btw. "[[ ]]" is Lua syntax for strings spanning multiple lines.

    Please login or register to see this code.

     

    Share this post


    Link to post
    Share on other sites

    Hi @jgab, another question. Sorry.

    I was trying to turn on the lights at 6:45 until sunrise + 30 mins. Although I understand why the below does not work (I think), I have trouble finding a neat way of doing this.

    Please login or register to see this code.

    NB: lights should not turn on if sunrise is before 06:45

     

    EDIT: 

    Nevermind, I think I found it:

    Please login or register to see this code.

     

    Let's wait until tomorrow morning to see whether it works ;D

     

    Edited by 3JL

    Share this post


    Link to post
    Share on other sites
  • Topic Author
  • 7 minutes ago, 3JL said:

    Hi @jgab, another question. Sorry.

    I was trying to turn on the lights at 6:45 until sunrise + 30 mins. Although I understand why the below does not work (I think), I have trouble finding a neat way of doing this.

    Please login or register to see this code.

    NB: lights should not turn on if sunrise is before 06:45

     

    Please login or register to see this code.

    Need to keep '>=' and '=>' apart :-) 

    3 minutes ago, jgab said:

     

    Please login or register to see this code.

    Need to keep '>=' and '=>' apart :-) 

    Typically one wants to turn on the light at sunrise or 6:45

    Please login or register to see this code.

    This will turn on the light 6:45 if sunset+30min is before that or otherwise at sunset+30min

    Edited by jgab

    Share this post


    Link to post
    Share on other sites

    Nice! Thanks!

     

    To clarify: if it is dark in the morning, lights should go on from 6:45 until the sun takes over. If not (i.e. during summer, sun rises before 6:00), the lights should remain off. The @math.max should do the trick!

    Edited by 3JL

    Share this post


    Link to post
    Share on other sites
  • Topic Author
  • 20 minutes ago, 3JL said:

    Nice! Thanks!

     

    To clarify: if it is dark in the morning, lights should go on from 6:45 until the sun takes over. If not (i.e. during summer, sun rises before 6:00), the lights should remain off. The @math.max should do the trick!

    Shouldn't it be something like below?

    Please login or register to see this code.

     

    Share this post


    Link to post
    Share on other sites
    1 hour ago, jgab said:

    Shouldn't it be something like below?

    Please login or register to see this code.

     

    Yes, you are right! Thank you very much! (again :) )

    Share this post


    Link to post
    Share on other sites
    Quote
    On 9/4/2018 at 7:38 AM, jgab said:

    The second syntax "|| >>" is a bit tricky. But it would allow you to do things like this (I don't know what codes your device returns).

    Btw. "[[ ]]" is Lua syntax for strings spanning multiple lines.

    Please login or register to see this code.

     

     

     

    Thanks! it works like charm

     

     I have another question - how to get level of slider from virtual device for comparing?

     

     

    Share this post


    Link to post
    Share on other sites
  • Topic Author
  • 34 minutes ago, petrkl12 said:

     

    Thanks! it works like charm

     

     I have another question - how to get level of slider from virtual device for comparing?

     

     

    Sliders are similar to labels.

    Please login or register to see this code.

     

    Share this post


    Link to post
    Share on other sites
  • Topic Author
  • The full blown

    Please login or register to see this link.

    framework has support for more advanced event programming than the EventRunnerLite described in the first post of this tutorial. In this post the script language implemented in the EventRunner framework will be described. The script language is particularly suitable for writing compact rules handling time scheduling, device triggering of rules, and user defined event rules. 

     

    This first part will describe how script rules can be used to define a flexible scheduler. A scheduler is a scene that runs actions at specific times during the day. A flexible scheduler can adjust its behaviour depending on day of week, month or state of global variables or state of other devices at that time.

     

    In the EventRunner framework, the 'main()' function is used to setup rules and is called before the framework starts. 'main()' can also be used to read in a HomeTable, setup variables etc, things that needs to be done once the framework starts up.

     

    To define a rule the 'Rule.eval(<string>)' function is used. A rule is a Lua string of the format "<condition> => <actions>", and is compiled to an efficient representation that is run when the <condition> is true. If the string doesn't contain a '=>' it is considered to be an expression that is just evaluated, and the result is returned. This can be useful to setup variables and other initializations.

    Please login or register to see this code.

    A scheduler runs actions at a specific time during the day, so we use the 'daily’ or '@' rules

    The generic form of a daily rule is "@<time> [<optional extra tests>] => <actions>"

    Please login or register to see this code.

    The rule will be called every day at 15:10, and the left-hand expression "@15:10" will evaluate to true (because it's 15:10) and thus the right-hand side if the '=>' will be carried out. In this case the lamp with deviceID 55 will be turned on.

    However, this also means that we can tuck on extra tests on the left-hand side that needs to be true for the rule to execute its actions. Any logic expression combining AND (&), OR(|), NOT(!), or comparison operators (==,>=,<=,~=) can be used.

    Ex. (we don't include the 'function main()' part in the examples from now on)

    Please login or register to see this code.

    This tests if the lamp also is off, and if so the lamp is turned on. It is important that there should be no "side-effects" on the left-hand side. No functions that turn on or off devices or set globals etc, only functions that query states.

     

    Here are some examples of types of rules that can be defined 

    Please login or register to see this code.

    The above rules run at sunrise every day and we add additional conditions that restrict it to sunrise at specific days and/or if a global variable also is set to a specific value or if a device is in a specific state.

     

    All 'daily/@' rules are 'examined' at midnight and the expression after the '@' character is computed and should return a number being the seconds after midnight the rule should be run. That is why there should be no side-effects in the left-hand side of the rule as they would be carried out at midnight, which we probably don't want. When the rule is later run at the computed/specified time, the whole left-hand side is computed again as a logical expression and if it returns true the right-hand side, the action(s), is run.

     

    'sunrise' and 'sunset' are constants that return seconds to sunrise and sunset respectively. Because the '@' expression is computed we can specify expressions like 'sunset+00:15' and it's computed as 15 min after sunset in seconds. Time constants like '04:15' are shorthand for '0+(60*(15+60*4))'. Seconds can also be specified '10:20:30' same as '30+(60*(20+60*10))'

    We can use a value from a global variable easily, but if we want to use the time notation we need to convert it to seconds because globals always return strings. The 'time' function converts a string with a time value to seconds. 

    Please login or register to see this code.

    or if we want to adjust and offset to 'sunrise' with a global variable, maybe controlled from a VD

    Please login or register to see this code.

     Remember that the times are calculated at midnight, so if the global is changed during the day it will not take effect until the next day (However, the scene can be restarted for all values to be re-calculated).

     

    A typical case is to turn on a light in the morning if that time is before sunrise

    Please login or register to see this code.

     This rule is run 06:00 every morning but the constant 'now', representing the current number of seconds since midnight, must be less than sunrise + 30min for the right-hand action to be run.

     

    Maybe a lamp should be turned on in the afternoon at sunset, given that sunset is within a certain time window (here in the north we can have sunset at 2PM)

    Please login or register to see this code.

     The '<time1>..<time2>' operator is true if the current time is between the specified times.

     

    To do something at a random interval every day, the 'rnd' function can be used. 'rnd(x,y)' returns a random number between x and y.

    Please login or register to see this code.

     Assume we have different wake-up times depending on day of week. A short alarm clock could look like this.

    Please login or register to see this code.

     This will at every midnight schedule the wakeup time associated with the weekday that we get from 'osdate' that takes same arguments as Lua's 'os.date'.

    '<ID>:send=<string>' send a text string to a phone with id ID. The 'log' command prints its message to the HC2 debug window but also returns the string which we then use as input to the ':send' command. We also make sure that our global variable 'Presence' is not set to 'Vacation', as we don't want any messages then.

     

    The '@' expression can also be applied to a list of times, and all will be scheduled. 

    If we want to do something at every 15min between 10:00 and 14:00, it's easiest to do something like this

    Please login or register to see this code.

    The advantage is that this is done every 15min between 10:00 and 14:00 every weekday and there is no time drift.

     

    There is another construct that schedule actions at specific intervals, the '@@' operator.

    Please login or register to see this code.

    This is an efficient way to do things at specified intervals. However, after a while there can be a drift

    Please login or register to see this code.

    It starts out on the 36th second every minute but after 4 days in this case we end up on the 37th seconds.

    Often this is not a huge problem if one needs to run some action at even intervals.

     

    Here is a really short presence simulator

    Please login or register to see this code.

     This runs at random intervals between 10 and 30min turning on/off lamps, when the global variable 'Presence' is set to 'away' and it's between sunset and sunrise. We select a random lamp from the 'lamps' table and call the ':toggle' function to toggle the state of the lamp.

    A more advanced presence simulator would save and restore lamp states before running, but that is for another post.

     

    One more note. In the examples above we have declared a local script variable ‘lamp’ that we use in the actions. It is easy to bring in HomeTable definitions to be used in the scripts.

    Assume there is a hometable that looks like this:

    Please login or register to see this code.

    The function ‘Util.defvars’ will declare the table as script variables.

    Please login or register to see this code.

    So, script rules allow us to write compact and flexible rules for scheduling actions. It's easy to integrate with a VD and fibaro globals to adjust rules for specific contexts. The syntax for the script language and available action functions is described in more detail here <

    Please login or register to see this link.

    >

     Next up is a post on trigger rules...

     

     

     

     

    Edited by jgab
    • Like 1

    Share this post


    Link to post
    Share on other sites

    @jgab need some expert help. My goal is to press a button on a VD after 40 minutes if Label1 is "ON"

     

    Please login or register to see this code.

     

    Share this post


    Link to post
    Share on other sites
  • Topic Author
  • 18 minutes ago, jompa68 said:

    @jgab need some expert help. My goal is to press a button on a VD after 40 minutes if Label1 is "ON"

     

    Please login or register to see this code.

     

    Single line version

    Please login or register to see this code.

    ...and don't forget declaring the label trigger in the scene header.

    The right hand side of '=>' can be a list of independent statements separated by ';' like many programming languages use. Because there is no 'if-then-else', I often code like '<test> & <action>' or '<test> & <action1> | <action2>' that is equivalent of 'if-then' or 'if-then-else'. (there is also a 'case' statement '|| <test1> >> <action1> || <test2> >> <action2> ...')

    P.S You need a reasonable new version of the EventRunner code. I pushed just the other day a version that allows triggers on 'label(id, name)' after a request from @petrkl12

    Edited by jgab

    Share this post


    Link to post
    Share on other sites
  • Topic Author
  • It can be really difficult to debug scenes on the HC2. 

    • There is no way to set break points so you are left to sprinkle the scene with fibaro:debug statements. 
    • The scene logic you thought through didn’t work because triggers from devices arrived in an non-anticipated order… i.e. there should be a way to replay sequences of triggers/events  to make sure that the scene logic is sound.
    • Waiting for triggers in real-time, triggers or time events that can be hours in between is really boring and unproductive when trying to find bugs in a scene – there should be some way to simulate a speed up of time for debugging purpose.

    Many of us do develop our scenes off-line, on PCs/Macs/Linux machines using libraries like the “Lualibs/FibaroSceneAPI”. However, it’s still not so easy to really debug scene logic involving triggers.
    The EventRunner framework is especially well suited for developing scenes off-line;

    • The programming model in EventRunner is event based, meaning we post and receive events to drive the scene logic (including device events). This means that we can replay sequences of  trigger/device events by posting fake events looking like device events, at chosen times. This allow us to see if our scene reacts in the way that we anticipated.
    • Because we run off-line we can put breakpoints in the code to understand what happens when triggers come in and follow the flow through the scene.
    • We can speed up the clock!  We can speed true a couple of days in a second and see if scene logic, like schedulers that usually act over time frames spanning days, behave as we would expect. We can do tricks like that because in the framework we control the clock…
    • ...and finally, we can run the same code off-line as we run on the HC2. When the code runs correct offline we can just cut and past it into a scene on the HC2 without changing a single line of code.

     

    This has made my own productivity raise with an magnitude compared to developing on the HC2… and it has allowed me to develop much more complex scenes – like the EventRunner framework scene itself – that I would never have dared to do on the HC2…

    So, to start running and debugging offline I recommend the following steps.

    • Install a Lua IDE – I would recommend

      Please login or register to see this link.

      . It's free and cross platform. I guess that any other would work. 
    • Please login or register to see this link.

      . The link also has a tutorial how to setup ZeroBrane.
    • Please login or register to see this link.

      , download 'EventRunner.lua' (or EventRunnerLite), 'EventRunnerDebug.lua', ’example_rules.lua', and ’devicemap.data’ and put them in your working directory
    • Fire up the IDE and load 'EventRunner.lua' and run it. It is setup to run test examples from the 'example_rules.lua' file (Note! The examples depends on the HomeTable definition in ’devicemap.data’). Play around with enabling other scenarios in that file.

    The magic for debugging scenes are in the 'EventRunnerDebug.lua’ file. This file is conditionally included in the scene framework code

    Please login or register to see this code.

    and ‘dofile’ is not available on the HC2 so the debug code is not included when you transfer the scene to the HC2. The goal have been that the one should be able to copy the whole scene from the off-line IDE to the HC2 without having to change a single line of code.
    Besides including the FibaroAPI and json libraries. EventRunnerDebug.lua is responsible for implementing HC2 functions that are missing in a standard offline Lua setup.

    • There are implementations of ‘setTimeout’ and ‘clearTimeout’. The framework relies on setTimeout instead of fibaro:sleep do post events at specific times. Having our own implementation also allows for tricks like speeding up the clock.
    • net.HTTPClient, api.get, api.put,api.post behaves similar to the HC2 versions. If you setup your HC2 credentials the api.xxx calls will call your HC2.
    • FibaroAPI is included so you can do remote fibaro:xxx calls to the HC2 (also needs your HC2 credentials). However, there is a _REMOTE flag that if set to false tries to simulate the fibaro:xxx calls locally when you don’t have access to the HC2 (or you don’t want to disturb the family with blinking lights)

    Top of EventRunnerDebug.lua contains some variables to control this behaviour

    Please login or register to see this code.

    There is also a global lua table with flags that can be set to 'true' to debug different parts of the framework

    _debugFlags = { 
      post=true,         -- Log all posts
      invoke=true,     -- Log all handlers being invoked (triggers, rules etc)
      rule=false,        -- Log result from invoked script rule
      triggers=false,  -- Log all externally incoming triggers (devices, globals etc)
      dailys=false,     -- Log all dailys being scheduled at midnight
      timers=false,    -- Log att timers (setTimeout) being scheduled)
      fibaro=true,       -- Log all fibaro calls except get/set
      fibaroGet=false  -- Log fibaro get/set
    }

    _debugFlags.rule can not be change while the scene is running as it instruments the rules with debug statements.

         

    If we load the example in the first post, the catching keypresses 1-2-3 from a fibaro keyfob and run it in the ZeroBrane IDE we get the output

    Please login or register to see this code.

    Here we see the output as expected. We see our posted fake key trigger events simulating the keyfobs CentralSceneEvents at 2seconds interval, and we see that our logic is correct.
    Trying out the Presence simulation example in the first post gives this trace

    Please login or register to see this code.

    Even if the scene takes an hour we speed through it in a second by having set the _SPEEDTIME variable to 48*4 in this case - but we still get the actual timing info in the debug statements so that we can see that it reacts at the right times.
    Here the _debugFlags.post and _debugFlags.fibaro is set to true so that posts to 'main()' and fibaro calls are written to the console. Debugging in the EventRunnerLite framework is a bit limited compared to the full EventRunner framework.

    Running a more complex example from the full EventRunner framework (the 'tHouse' example from 'example_rules.lua') gives this trace below. Here the example use the script language for rules and we have set the _debugFlags.invoke=true which logs when the rules are invoked/triggered. This runs over a couple of days but with _SPEEDTIME set it takes less than a second. The example also sets the clock to 08:00 at startup, that's why we see the jump from 15:48 to 08:00 in the beginning of the log. It's very practical to be able to run scenes at simulated times of the days.

    Please login or register to see this code.

    Support for debugging is something that always can be improved, and debugging of script rules could be improved to further.

    Edited by jgab
    • Like 1

    Share this post


    Link to post
    Share on other sites

    Hi colleague! 

     

    btw. my fibaro_emu.lua have in first the  line  

    local is_mock = false;

    (see attachment file)

     

    and folder data  contain json files with id's (device)

     

    so I can simple debug any events here. It's easy :)

    Please login or register to see this attachment.

    Edited by 10der

    Share this post


    Link to post
    Share on other sites
  • Topic Author
  • Nice, that gives you local emulation of fibaro calls (you remove the json files when re-running the scene to come back to the same state?).

    The trick is, and what is important when finding bugs in a scene, is to debug *incoming* events in a realistic model. That's why an event model is so suitable - it allows you to play up sequences of events and you can debug how the code reacts. Combine that with control over the clock-speed to debug "faster than real-time", and you have some of the ingredients to simply debug scenes.

    Edited by jgab

    Share this post


    Link to post
    Share on other sites
    10 minutes ago, jgab said:

    you remove the json files when re-running the scene to come back to the same state?

    some sorf of :

    I am editing files :)

    for example 

    Please login or register to see this image.

     

    but. your idea made it automatically good. rnd + clock. 

     

    Share this post


    Link to post
    Share on other sites

    Create an account or sign in to comment

    You need to be a member in order to leave a comment

    Create an account

    Sign up for a new account in our community. It's easy!

    Register a new account

    Sign in

    Already have an account? Sign in here.

    Sign In Now

    ×