Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

How to write the response from a network.request() to a variable?
Started by ray6 Feb 03 2020 04:29 PM

3 replies to this topic
network networklistener asynchronous blocking non-blocking network.request

Best Answer SGS , 03 February 2020 - 06:26 PM

In your code zumlink_response is global so therefore it's state is persistent.  You also cannot return the response to a network request in the code block - requests are not blocking. 

 

You are also going to need a callback function to send the data too.  So you need a function in your scene that can accept (and process) the response.  So when you call sendComand() you would show a spinner or some feedback to the user and cancel this in your callback function.

 

 

Something like this

local callbackFunction

local function networkListener( event )
  if not event.isError
    print( "In networkListener, RESPONSE: " .. event.response )
    callbackFunction(event.response)  <-- send response to callback function -passed into sendComand()
  end
end

function sendCommand( ip, command, callback )
  local cmd = {}
  cmd.command = command
  local url = "http://admin:admin@" .. ip .. "/cli/" .. cmd.command
  callbackFunction = callback   <-- cache callback
  network.request( url, "GET", networkListener, params )
end

[TOPIC CONTROLS]
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#1

ray6

[GLOBAL: userInfoPane.html]
ray6
  • Observer

  • 11 posts
  • Corona SDK

I've read everything that I can find about this in the forums and the docs, and clearly I'm missing something important, but I have no idea what it is.

 

I'm sending a GET request to a network device and I want to save its response in a variable that I can use. Starting from the sample code in https://docs.coronalabs.com/api/library/network/request.html, I've created the following code snippet:

local function networkListener( event )
  if( event.isError ) then
    print( "Network error: ", event.response)
  else
    print( "In networkListener, RESPONSE: " .. event.response )
    zumlink_response = event.response
  end
end

-- This stuff is useful if you're going to do a get.
local headers = {}
headers["Content-Type"] = "application/x-www-form-urlencoded"
headers["Accept-Language"] = "en-US"
headers["Authentication"] = "admin:admin"
local body = "color=red&size=small"
local params = {}
params.headers = headers
params.body = body


-- Return a string which is the JSON object. 
-- Let the calling function sort it out.
function zumlink.cmd( ip, command )
  local cmd = {}
  cmd.command = command
  local url = "http://admin:admin@" .. ip .. "/cli/" .. cmd.command
  print( url )
  network.request( url, "GET", networkListener, params )
  print( "In zumlink.cmd: zumlink_response is [" .. zumlink_response .. "]" )
  return zumlink_response
end

So, the calling function calls zumlink.cmd(), passing it the IP address of the connected device and the command "systemInfo". As zumlink.cmd() exits, it prints the contents of zumlink_response, which is empty because networkListener() hasn't executed yet. It also passes the empty zumlink_response to the calling function. Then the networkListener() executes, and writes a value to zumlink_response.

 

If I execute the calling function again, we go through the same routine, but this time zumlink_response already contains something, and so zumlink.cmd() prints the contents of zumlink_response and passes it to the calling function. Then the networkListener() executes and writes a new value to zumlink_response. (In the printout below, the new value is identical to the old value, but that's just coincidence.)

Here's the output:

-- The line at 16:15:02.385 is the output from "print( url )" in my code snippet.
-- It's just there to tell me what was sent to the connected device.
16:15:02.385  http://admin:admin@192.168.137.32/cli/systemInfo
16:15:02.396  In zumlink.cmd: zumlink_response is []
16:15:02.396  systemInfo retval is []
16:15:02.568  In networkListener, RESPONSE: [{"RESPONSE":{"pages":{"systemInfo":{"deviceConfiguration":"R1","deviceFirmwareVersion":"FWT1314TB.8","deviceId":"1","deviceModel":"Z9-PE2","deviceName":"","hopTableVersion":"SET0101HT","layoutHash":"2902858855","licenses":"Custom Apps","modelCode":"0","radioFirmwareVersion":"FWT1072TR.43","radioModel":"AMT0100AA","radioModelCode":"0","radioSerialNumber":"4026803732","resetInfo":"","rteTemplateVersion":"FWT1311TP.3","rteVersion":"FWT1311TP.3","serialNumber":"4026803732","themeVersion":"FWT1314TB.8"}}},"RESULT":{"MESSAGE":"OK","RESULT":0}}]
16:15:02.568  


-- Second time through. Again, the line at 16:15:25.785 is the "print( url )" output.
16:15:25.785  http://admin:admin@192.168.137.32/cli/systemInfo
16:15:25.785  In zumlink.cmd: zumlink_response is [[{"RESPONSE":{"pages":{"systemInfo":{"deviceConfiguration":"R1","deviceFirmwareVersion":"FWT1314TB.8","deviceId":"1","deviceModel":"Z9-PE2","deviceName":"","hopTableVersion":"SET0101HT","layoutHash":"2902858855","licenses":"Custom Apps","modelCode":"0","radioFirmwareVersion":"FWT1072TR.43","radioModel":"AMT0100AA","radioModelCode":"0","radioSerialNumber":"4026803732","resetInfo":"","rteTemplateVersion":"FWT1311TP.3","rteVersion":"FWT1311TP.3","serialNumber":"4026803732","themeVersion":"FWT1314TB.8"}}},"RESULT":{"MESSAGE":"OK","RESULT":0}}]
16:15:25.785  ]
16:15:25.785  systemInfo retval is [[{"RESPONSE":{"pages":{"systemInfo":{"deviceConfiguration":"R1","deviceFirmwareVersion":"FWT1314TB.8","deviceId":"1","deviceModel":"Z9-PE2","deviceName":"","hopTableVersion":"SET0101HT","layoutHash":"2902858855","licenses":"Custom Apps","modelCode":"0","radioFirmwareVersion":"FWT1072TR.43","radioModel":"AMT0100AA","radioModelCode":"0","radioSerialNumber":"4026803732","resetInfo":"","rteTemplateVersion":"FWT1311TP.3","rteVersion":"FWT1311TP.3","serialNumber":"4026803732","themeVersion":"FWT1314TB.8"}}},"RESULT":{"MESSAGE":"OK","RESULT":0}}]
16:15:25.785  ]
16:15:25.954  In networkListener, RESPONSE: [{"RESPONSE":{"pages":{"systemInfo":{"deviceConfiguration":"R1","deviceFirmwareVersion":"FWT1314TB.8","deviceId":"1","deviceModel":"Z9-PE2","deviceName":"","hopTableVersion":"SET0101HT","layoutHash":"2902858855","licenses":"Custom Apps","modelCode":"0","radioFirmwareVersion":"FWT1072TR.43","radioModel":"AMT0100AA","radioModelCode":"0","radioSerialNumber":"4026803732","resetInfo":"","rteTemplateVersion":"FWT1311TP.3","rteVersion":"FWT1311TP.3","serialNumber":"4026803732","themeVersion":"FWT1314TB.8"}}},"RESULT":{"MESSAGE":"OK","RESULT":0}}]
16:15:25.954  

So I know what's happening, and I know why it's happening. I know that I need to wait for networkListener() to write to zumlink_response. But I don't  know how. It doesn't matter to me whether the wait is blocking or non-blocking. How do I do it? What am I missing? I'm sure it's something simple ...



[TOPIC: post.html]
#2

agramonte

[GLOBAL: userInfoPane.html]
agramonte
  • Corona Geek

  • 1,377 posts
  • Corona SDK

If you want to block the entire thing you can use a while loop. Stay in the loop until the variable is not null. Not sure if this will block the listener, but I don't think so.

while zumlink_response == nil do
-- Nothing.
end

It would be better if you don't block. Fire the event and then just wait for the response before doing whatever you are doing. The response can call whatever you are calling after the event returns. Show some UI that says it is waiting for a response. A spinner. Anything really.


  • ray6 likes this

[TOPIC: post.html]
#3

SGS

[GLOBAL: userInfoPane.html]
SGS
  • Corona Geek

  • 2,205 posts
  • Corona SDK

  Best Answer

In your code zumlink_response is global so therefore it's state is persistent.  You also cannot return the response to a network request in the code block - requests are not blocking. 

 

You are also going to need a callback function to send the data too.  So you need a function in your scene that can accept (and process) the response.  So when you call sendComand() you would show a spinner or some feedback to the user and cancel this in your callback function.

 

 

Something like this

local callbackFunction

local function networkListener( event )
  if not event.isError
    print( "In networkListener, RESPONSE: " .. event.response )
    callbackFunction(event.response)  <-- send response to callback function -passed into sendComand()
  end
end

function sendCommand( ip, command, callback )
  local cmd = {}
  cmd.command = command
  local url = "http://admin:admin@" .. ip .. "/cli/" .. cmd.command
  callbackFunction = callback   <-- cache callback
  network.request( url, "GET", networkListener, params )
end

  • ray6 likes this

[TOPIC: post.html]
#4

ray6

[GLOBAL: userInfoPane.html]
ray6
  • Observer

  • 11 posts
  • Corona SDK

It worked. Thanks to @agramonte and @SGS for your help.




[topic_controls]
[/topic_controls]

Also tagged with one or more of these keywords: network, networklistener, asynchronous, blocking, non-blocking, network.request