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


paced HTTPClient() requests


jgab

Recommended Posts

In scenes, net.HTTPClient:request is asynchronous. 

It means that it does the request and when the result is returned (at a later time) it calls our 'success' or 'error' handler

This also means that we can send requests quicker than we get responses back from the server.

 

Ex. if requests with commands are sent to a Hue bridge quicker than it manages to respond it fairly quickly starts to drop commands. The same with a service like Telegram.

The solution is to not send requests quicker than we get responses back (success or error).

There are various ways to manage that in the code but it can become quite complex... 

So here is a "drop in replacement" for net.HTTPClient() named netSync.HTTPClient that queue up the requests. No change in semantic.

Please login or register to see this code.

 

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

  • Topic Author
  • .

    Edited by jgab
    Link to comment
    Share on other sites

  • Topic Author
  • It depends on the service, but lets use Hue as an example 

    (if you use the Hue plugin  and fibaro:calls to set the lights you may not run into this issue, and in VDs the http request is synchronous)

    Please login or register to see this code.

    This will generate "Connection reset by peer" errors as the Hue bridge can't cope with so many (parallell) incoming requests.

    Please login or register to see this code.

    works fine...

    Anyway, many services has an issue with too many outstanding requests, and this can solve it by pacing the requests.

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

    Guest Lode

    Nice work !!

    I wrote this small piece of code to turn some Hue lights on when a sensor is breached.

    So this is what it does..

    First look if the lights are on/off, brightness, saturation and what color.

    Second change the lights to red full brightness and saturation.

    At last change everything to its original state as saved in the table.

    9 times out of ten it works but sometimes a light doesn't go back to its original state or something else happens.

    How can i implement your code to prevent this ?

    Thanks ?

    Please login or register to see this code.

     

     

    Edited by Lode
    Link to comment
    Share on other sites

  • Topic Author
  • 3 hours ago, Lode said:

    Nice work !!

    I wrote this small piece of code to turn some Hue lights on when a sensor is breached.

    So this is what it does..

    First look if the lights are on/off, brightness, saturation and what color.

    Second change the lights to red full brightness and saturation.

    At last change everything to its original state as saved in the table.

    9 times out of ten it works but sometimes a light doesn't go back to its original state or something else happens.

    How can i implement your code to prevent this ?

    Thanks ?

    Please login or register to see this code.

     

     

    Your problem is not really applicable as you use the fibaro:call functions to change the lights. I haven't seen any issue with those and I expect them to use synchronous calls in the plugin.

    If you suspect that it's the speed that's causing the trouble you can insert a small sleep after each call. Put something like this in the beginning of the scene:

    Please login or register to see this code.

    However, I don't think that's your problem.

    You have a strange loop here

    Please login or register to see this code.

    the inner loop will do fibaro:call(v,..) with v bound to ID, On, Hue, Saturation, Brightness of each Hue light saved which is not your intention. (You may accidentally turn on some other lights)

    Just do

    Please login or register to see this code.

     

    Edited by jgab
    Link to comment
    Share on other sites

    Guest Lode

    @jgab Thank you very much for your answers. I really appreciate this.

    I changed the code like you said and i can see a pause while the lights changing.

    I will observe this for a while and give you some feedback.

    There is one more thing i want to ask you....

    I really don't undestand how this works

    Please login or register to see this code.

    I'm a VBA programmer and not so good in LUA but i want to understand things ?

    Link to comment
    Share on other sites

  • Topic Author
  • So, Lua is actually a very nice language and even if Fibaro have restricted the language for us, we can still modify it quite a bit.

    Please login or register to see this code.

    is the same as

    Please login or register to see this code.

    foo is just a variable set to a function value.

    That means that we can easily redefine an existing function by setting the function name to some other function (this can also cause unexpected bugs if we accidentally redefine a standard function like 'json')

    Please login or register to see this code.

     

    Now we have a new definition of foo that first prints out the log text and then calls the original foo.

     

    We can store functions in a Lua table

    Please login or register to see this code.

    ...and call them like

    Please login or register to see this code.

    ...but this is more convenient

    Please login or register to see this code.

     

    If we have a table

    Please login or register to see this code.

    we can do

    Please login or register to see this code.

    ...to add a key-value pair and we get the table  {foo = 6}

    We can use the same syntax to assign a function the key 'foo'

    Please login or register to see this code.

    ...and Lua allows us to use the function definition syntax

    Please login or register to see this code.

    Note, tab needs to be an existing table or we get an error (Lua tries to do tab['foo']=function(x) return x+x end )

     

    Lua has a special syntax for "object oriented" functions and function calls

    Please login or register to see this code.

    Which Lua translates to 

    Please login or register to see this code.

    and you can call it like

    Please login or register to see this code.

    ...and it translates that to 

    Please login or register to see this code.

    e.g. it sends the table that foo was in (tab) as the first argument to foo bound to self. 

    This allows for some "Object oriented " style of programming. We can store some object properties in 'tab' that foo can use etc...

    However, the point here is that fibaro:call and other fibaro:* functions are of this style.

    So 'fibaro' is a table with a lot of functions

    Please login or register to see this code.

     

    So in my example I saved away the old fibaro.call value

    Please login or register to see this code.

    and set fibaro.call to a new function that waits 200ms before calling the original fibaro.call

    Please login or register to see this code.

    and I wrapped it in a do...end block so the local oldCall would not be visible outside that operation.

    Oh, '...' in the argument list captures a variable number of arguments and we just pass that on to the original fibaro.call.

     

    This way we can "patch" existing functions to extend their functionality.

    Wouldn't it be cool with a fibaro:call(<deviceID>,"toggle") to toggle a light? turn on if off and off if on.

    Please login or register to see this code.

    now we can do

    Please login or register to see this code.

    Another case, it turns out that fibaro:debug uses the function 'tostring' to convert the argument to something that can be printed

    Please login or register to see this code.

    Whenever we try to do fibaro:debug(42) we get the string printed out instead.

     

    This can also be useful.

    Assume we have a data structure, a table, that represents a time interval. Ex. {startDate=os.time(), endDate=os.time()+24*3600}

    and we use them a lot in our code and would like to print them easily

    We can do a generic extension of tostring that have custom conversion of tables

    Please login or register to see this code.

    every Lua table that have a .__tostring field will call that function to convert the table to a printable representation when you do fibaro:debug, print or tostring

    A simple thing is to set myTable.__tostring = json.encode

    and you will get a json printout of the table instead of the non-informative "table: 0x67876"

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

    Guest Lode

    WOW........i didn't know anything about all that functionality.

    This is completely new to me but SO INTERESTING to read and learn.

    I don't fully understand it all but i won't give up before i do.

    How can i thank you for putting so much effort to help me out !!

    Many many many thanks @jgab !!!!!!!!!!

    Btw i tried the Hue lights about 30 times with the changes you made and it works perfect !!

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