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

HTTP call from LUA to retrieve information


FamSetsaas

Question

Dear experts,

 

I'm trying to do an HTTP call from LUA, to retrieve the external IP address. However, it is obvious that I need to wait for the response, but have not been able to find out exactly where to do this. Here is my code:

 

function myPublicIP(str)
    fibaro:debug("A")
    str = "https://api.ipify.org/?format=json"
    local http = net.HTTPClient()
    fibaro:debug("B")
    http:request(str, {
          success = function(status)
          fibaro:debug("C")
          fibaro:debug(status.status)
          if status.status ~= 200 and status.status ~= 201 then fibaro:debug("failed"); end
          fibaro:debug("D")
          fibaro:debug(status.data);
           
        result = json.decode(status.data)
        ip = result.ip
         fibaro:debug("E")
        fibaro:debug(ip)
        
        end,
        error = function(err)
          fibaro:debug('[ERROR] ' .. err)
        end
      })
  fibaro:debug("F")
  return ip
end -- function


fibaro:debug("G")
fibaro:debug(myPublicIP())

 

When running this, the debug output after "E" shows that the IP address is retrieved correctly. But this comes too late, and the function returns nil. So there is a need for a sleep (which I guess is the simplest) somewhere, but have not figured this out.

I do not really understand how the code is executed. The letters are output in this order: G A B F C D E. So I just need to ensure that C D E are completed before continuing to F.

 

 

Any help would be appreciated.

 

 

Link to comment
Share on other sites

8 answers to this question

Recommended Posts

  • 0
  • Inquirer
  • Hi,

     

    I must be missing something.

    I want the function myPublicIP to return the value of IP address.

     

    Could you please update my code so that the myPublicIP function returns this value?

    Thank you

    Link to comment
    Share on other sites

    • 0

     

    Please login or register to see this image.

    /monthly_2020_08/image.png.4be2c4e4409e2ba9e8960a4cc44170f1.png" />

     

    image.png.56981a7d2b1f7ec38c0b89a15f8d64cb.png

     

    Please login or register to see this code.

     

     

     

     

    Link to comment
    Share on other sites

    • 0
    3 hours ago, FamSetsaas said:

    Hi,

    I must be missing something.

    I want the function myPublicIP to return the value of IP address

    Could you please update my code so that the myPublicIP function returns this value?

    Thank you

     

    Your myPublicIP can't return the value. When your scene starts it runs in a "main process". The http request creates a new process and will call your success/error functions in that process.

    It look like this (I have added a debug("H") last in the scene)

    Please login or register to see this attachment.

    Normally when we think about process we imagine them running in parallell. However Lua have co-operative processes, or as they are called "coroutines".

     

    Note that coroutines/processes run in the same "scene instance" on a HC2/HC3 - it's not multiple scene instances - and a HC3 QA starts with a main process and then spawns new processes for incoming fibaro.calls or button presses (or http:requests)

     

    What that means is that only one process can run at any given time. 

    When the main process calls http:request(), that calls returns immediately and myPublicIP returns "ip" that haven't got a value yet.

    When the main process is done (the last debug "H") the http process/callback can start.

    It gets the success data, decodes it, and sets "ip" to the value.

    Then it terminates. Your main process has already terminated and can't print the result.

     

    Some people have tried to do a fibaro:sleep in the main process to wait for the http process to finish. But we know now that this doesn't work as the main process needs to terminate before the http process can start. (fibaro:sleep just blocks the current coroutine for a given time but don't let any other coroutine run)

     

    So how do we solve this? Well, we do like @10der does in his example. We provide the myPublicIP with a "continuation function". A function that the http process should continue to execute when it has got the result.

    Please login or register to see this code.

     

    Please login or register to see this attachment.

     

    When we do "setTimeout" we actually start a Lua coroutine. However, other coroutines need to finish before it can start.

    When we do setTimeout loops like

    Please login or register to see this code.

    Every call to loop prints "OK" and starts a new coprocessor that should start in 1s, and then it terminates - allowing other coroutines to run.

    Please login or register to see this attachment.

     

    That's why we can start many "loops" that cooperate and seems to run in parallell.

    Edited by jgab
    • Like 1
    • Thanks 4
    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
    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...