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


SourceTriggerSubscriber


jgab

Recommended Posts

In the new FW we have the

Please login or register to see this link.

functionality that allow us to subscribe to "raw" HC3 events from the /refreshState API.

For scenes these events are "refined" to sourceTriggers that we can use as condition triggers.

 

Please login or register to see this link.

 is nice to have built-in for simple stuff but is a bit clunky to use for more complex stuff. Also, the filter-handler model forces it to go through all filters for all events - no keying on event fields - so in may not scale so well...

 

So, here is a SourceTriggerSubscriber class (can be put in a separate QA file as a library). In leverages the RefreshStateSubscriber but register a SourceTrigger pattern we want to handle and a function to call if the pattern match.

Please login or register to see this spoiler.

It only register one filter-handler with the RefreshStateSubscriber and then does it's own efficient lookup for a matching handler. 

Please login or register to see this code.

The event given to :subscribe is a pattern that is matched, and if no contradictions, the handler will be called

{type='device', id=66, property='value'} only matches device events from device 66 and property 'value'

{type='device', id=66} matches device events from device 66 and any property

etc.

The event given to the handler is the full event that was matched and we can inspect other fields of the event...

 

It's actually a little bit more clever... instead of values in the pattern we can give a "variable match" to extract specific values from the event. In this case we get another argument to the handler function that is a table with the variables and their values

Ex.

Please login or register to see this code.

We match with the value string "$<variableName>" and we get a table with the variableNames set to the matched values. 
In this example we match against the keyId and keyAttribute fields in the sourceTrigger to extract them.

 

The events currently supported (I have seen) are listed below. It's more types of source triggers than what we have in scenes, but some of them are useful...
Feel free to add and improve on the list - it's a task of mapping RefreshState events into something interesting expressed as a sourceTrigger....

Please login or register to see this code.

 

API

Please login or register to see this code.

 

 

debugFlags

Please login or register to see this code.

 

Edited by jgab
  • Like 1
  • Thanks 4
Link to comment
Share on other sites

  • 2 weeks later...
On 11/22/2023 at 9:00 AM, jgab said:

Please login or register to see this code.

 

Hi! Finally, we get this functionality. Wonderful class, I appreciate an author for sharing it.

 

Could you please help me with one thing? How to correctly unsubscribe? What should I use as an argument?

My idea is to change subscriptions dynamically. Do I need to unsubscribe from the previous one first and then subscribe again with a new pattern? Or is it possible to just "overwrite" subscription by overwriting sts variable?

 

Thanks in advance.

Link to comment
Share on other sites

  • Topic Author
  • So, when you subscribe it will return a "Subscription" object.

    You give that object to unsubscribe.

     

    Yes, you need to unsubscribe and subscribe again - but you can have any number of subscription active in "parallel"

     

    There is also 

    function SourceTriggerSubscriber:enableSubscription(subscription)
    subscription.enable()
    end
    function SourceTriggerSubscriber:disableSubscription(subscription)
    subscription.disable()
    end

     

    that disables and enables a subscription temporarily...

    Link to comment
    Share on other sites

    Not clear enough....

     

    Based on your example:

    On 11/22/2023 at 9:00 AM, jgab said:

    Please login or register to see this code.

     

    Let's say, I want to subscribe for 1 minute and then unsubscribe:

     

    Please login or register to see this code.

     

    Quote

    sts.lua:375: attempt to concatenate a table value

     

    What I am doing wrong?

     

    Thank you.

    Link to comment
    Share on other sites

  • Topic Author
  • 10 hours ago, cashe said:

    Not clear enough....

     

    Based on your example:

     

    Let's say, I want to subscribe for 1 minute and then unsubscribe:

     

    Please login or register to see this code.

     

     

    What I am doing wrong?

     

    Thank you.

     

    Hmm, there seems to be something else going on here - your example runs very well for me and does the unsubscribe. What is line 375 in sts?
     

    It allows to unsubscribe, but usually one subscribes to a number of sourceTriggers one is interested in and then inside the handler function decides if it should be handled or not.

    Ex.

    Please login or register to see this code.

     

    Also, if you don't want any subscription callbacks from a subscription you can disable it. The advantage is that you can quickly enable it later.

    Please login or register to see this code.

     

    Edited by jgab
    • Like 1
    Link to comment
    Share on other sites

    8 minutes ago, jgab said:

    It allows to unsubscribe, but usually one subscribes to a number of sourceTriggers one is interested in and then inside the handler function decides if it should be handled or not.

     

    Yes, sure, I am processing like that already. But I thought that the more devices I subscribed -> the more load on HC. My idea was to disable some devices from the subscription from time to time.

     

    27 minutes ago, jgab said:

    What is line 375 in sts?

     

    Please login or register to see this image.

    /monthly_2023_12/image.png.d96e9cfee45d7ecb4ed1bd49c624e04d.png" />

     

    Thank you!

     

    Link to comment
    Share on other sites

  • Topic Author
  • 15 minutes ago, cashe said:

     

    Yes, sure, I am processing like that already. But I thought that the more devices I subscribed -> the more load on HC. My idea was to disable some devices from the subscription from time to time.

     

     

    Please login or register to see this link.

     

    Thank you!

     

    So, your 'obj' seems to be changed before you unsubscribe. Are you reusing the variable obj in some kind of loop?

    Try do print it out before you unsubscribe. Pay attention to the 'event' field, it should look like event={type="device",id=66,property="value"} in your case

    Please login or register to see this code.

     

     

    Well, the pattern matching to find the right handler to call is pretty efficient. It tries to hash on known fields of the event as much as possible.

    I have applications where people have hundreds of "subscriptions" with very little load.

    • Like 1
    Link to comment
    Share on other sites

    On 11/22/2023 at 9:00 AM, jgab said:

    The events currently supported (I have seen) are listed below. It's more types of source triggers than what we have in scenes, but some of them are useful.

     

    Is there any template for subscription on the Irrigation schedule change?

    Link to comment
    Share on other sites

  • Topic Author
  • 15 hours ago, cashe said:

     

    Is there any template for subscription on the Irrigation schedule change?

    Doesn't seem to be an refreshEvents when irrigation schedules are changed.

    • Like 1
    Link to comment
    Share on other sites

    On 12/8/2023 at 9:52 AM, jgab said:

    Doesn't seem to be an refreshEvents when irrigation schedules are changed.

     

    Thank you.

     

    Is there maybe cron (time-based events) possibility?

    Link to comment
    Share on other sites

  • Topic Author
  • 1 hour ago, cashe said:

     

    Thank you.

     

    Is there maybe cron (time-based events) possibility?

    You want when the scheduled time changes or when the irrigation starts?

    Link to comment
    Share on other sites

    1 hour ago, jgab said:

    You want when the scheduled time changes or when the irrigation starts?

     

    No, this is just another task already ))

    I meant that the subscription event triggered at some particular time (just like cron trigger in scenes, but in QuickApp).

    Link to comment
    Share on other sites

  • Topic Author
  • 12 hours ago, cashe said:

     

    No, this is just another task already ))

    I meant that the subscription event triggered at some particular time (just like cron trigger in scenes, but in QuickApp).

     

    No, not the present code - I just did an update of the code in the first post that allows for posting events at specific times-

    Ex.

     

    Please login or register to see this code.

     

    This creates 3 loops with different intervals

    Used like this it's like a setTimeout loop (or rather setInterval)

    The time string "+/hh:mm:ss" means "plus" time from now 

     

    However, we can also specify an absolute time

    Please login or register to see this code.

    and it will run at 15:30.

    "t/hh:mm:ss" means time (t)oday

    There is a small problem here. If time when we start this is past 15:30 the post will not be posted as time has passed....

     

    To the rescue is the prefix "n/" that posts at time today, or if time has passed, the same time next day. (n) as in (n)ow or (n)ext day

    Please login or register to see this code.

    This will post a loop that runs 15:30 every day. If we start it after 15:30 it will run its first loop next day 15:30.

    ...and it will never drift because the n/ and t/ calculates the exact time to delay every time.

     

    The drawback with this is that we can only set daily times - there is no way to make a post for only Thursdays.

    On the other hand it's very efficient because we only set a timer when we want to be posted.

    A cron function (also in Scenes) needs to run the condition every minute, every hour, every day, every week, every month, every year... to see if the condition is true.

     

    We could check if we have a "day" condition and only run the action then

     

    Please login or register to see this code.

     

    and it would just run once a day checking if it should run the action - actually more efficient than cron... We could extend this with days and months...

     

    One more trick. The string time also allows for specifying sunset or sunrise. and for those we also allow an offset

    Please login or register to see this code.

    This runs an action 15min before sunset every day.

     

    Instead of the elaborate st:post that needs to specify the event and the time (twice) we could do an helper function

    Please login or register to see this code.

     

    and do

    Please login or register to see this code.

     

    Note that st:post returns the timer reference, so we can do

    Please login or register to see this code.

    if the event is not posted yet - if we change our mind...

    Edited by jgab
    • Like 1
    Link to comment
    Share on other sites

    Fantastic, thank you!

     

    Is there any way to run action every day, every hour at XX:15, for example?

    Link to comment
    Share on other sites

  • Topic Author
  • 2 hours ago, cashe said:

    Fantastic, thank you!

     

    Is there any way to run action every day, every hour at XX:15, for example?

    well, the usual method would be to run something every midnight and schedule the times for the upcoming day.

    In this case 15 min past every hour 00-23. 

    Please login or register to see this code.

     

    However, it made me think and I've added the h/ time string prefix that resolves the the next hour 

    st:post(event,"h/mm:ss") will post the event mm:ss past the current hour, or if the time has passed, the same offset the next hour.

     

    So a loop posting 15min past every hour would be

     

    Please login or register to see this code.

    using the previous runAt function

     

    Edited by jgab
    • Thanks 1
    Link to comment
    Share on other sites

  • Topic Author
  • With the new h/ prefix we can easily create a more powerful runAt function, with a corresponding stopAt that stops the loop.

     

    Please login or register to see this code.

    runAt takes a time and a boolean 'interval' if the function should be repeated. It then takes the function and an option boolean catch parameter.

    If catch is true, the function is run even if the time has passed - catchup.

     

    So, If we want a function to run 15min past the hour between 15:00 and 19:00 we can write

    Please login or register to see this code.

     

    • Thanks 1
    Link to comment
    Share on other sites

    • 5 weeks later...

    hi, I am trying to get the weather status for my quickapp. 

    I know for sure it is Cloudy outside, I have med 7 scenes with conditions and a trigger to push witch state it is now. 

     

    ----{type='weather',property=<string>, value=<number>, old=<number>}
     local SubWeathersnow = SourceTriggerSubscriber()
        SubWeathersnow:subscribe(
    {type='weather',property= "weatherCondition", value="cloudy"}, ------------partlyCloudy   fog    clear   storm   snow   rain    cloudy----------
    function(event)      
    print("SubWeathersnow")
     
    SubWeathersnow:stop()
    print("SubWeathersnow2")
    end)
    -----oninit-------
    SubWeathersnow:run()

     

    I guess I am using this wrong?

    ----{type='weather',property=<string>, value=<number>, old=<number>}

     

     

     

     

     

     

     

    Link to comment
    Share on other sites

  • Topic Author
  • On 1/14/2024 at 11:15 AM, Brors94 said:

    hi, I am trying to get the weather status for my quickapp. 

    I know for sure it is Cloudy outside, I have med 7 scenes with conditions and a trigger to push witch state it is now. 

     

    ----{type='weather',property=<string>, value=<number>, old=<number>}
     local SubWeathersnow = SourceTriggerSubscriber()
        SubWeathersnow:subscribe(
    {type='weather',property= "weatherCondition", value="cloudy"}, ------------partlyCloudy   fog    clear   storm   snow   rain    cloudy----------
    function(event)      
    print("SubWeathersnow")
     
    SubWeathersnow:stop()
    print("SubWeathersnow2")
    end)
    -----oninit-------
    SubWeathersnow:run()

     

    I guess I am using this wrong?

    ----{type='weather',property=<string>, value=<number>, old=<number>}

     

     

    You only get a trigger when the weather changes. You will not be called immediately when the QA starts up.

     

    • Thanks 1
    Link to comment
    Share on other sites

    35 minutes ago, jgab said:

     

    You only get a trigger when the weather changes. You will not be called immediately when the QA starts up.

     

    Ah thenks. that explains why it is so hard to get the value 😅

    Link to comment
    Share on other sites

  • Topic Author
  • You could post the current values "to yourself" when you start up so your handlers triggers. 

    Please login or register to see this code.

     

    I see you call :stop in the handler so you will only get the first trigger, not when the weather changes again...

    ...and the handler will only trigger if it's cloudy... leave that out if you want triggers for every condition

    Oh, and the property is with capital letter.

    Edited by jgab
    • Thanks 1
    Link to comment
    Share on other sites

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