As the title says... Chat on...

User avatar
By katz
#13448 Hi,

The code below almost does what I want it to do. I can get the date and time from an external website (esp8266.com in this case). But I cannot access the local variable 'dtm' outside the function. The last two lines in the code should give the same result, but they don't. Is there a way around this?

Thanks, Peter.

Code: Select allgdtm="xxx"

function getURLdate(url)
   sk=net.createConnection(net.TCP, 0)
   sk:on("receive", function(sck, reply)
      --print(reply)
      i=string.find(reply,"Date: ")
      dtm=string.sub(reply,i+6,i+35)
      _G[gdtm]=dtm     -- make sure that dtm is global
      print("Local date = "..dtm)
      sk:close()
      end )
   sk:send("GET / HTTP/1.1\r\nHost: "..url.."\r\n\r\n")
   sk:connect(80,url)
end

getURLdate("esp8266.com")
print("Global date = "..gdtm)
User avatar
By cal
#13478 Moin Peter,

you are mixing up a few things.

1. synchronous calls versus asynchronous calls

synchronous: you call a function and get a result
asynchronous: you tell lua to call you back when something happens (called nodejs style on the example page)

Your function content is using asynch but you seem to expect a sync result.
Normally you would want a synch call. But unfortunately I don't know how to do that on nodemcu
and didn't find an example.
If you want to do it async put your action call into the "receive" callback you install.
If someone knows I would like to know, too!

2. When you call a function 'getURLdate("esp8266.com")' the function is called but you don't do anything
with the result. Either add a "=" before the call or do a "print(...)" of the value.
But before that you have to fix 1.) because you don't have a result.

Hope that helps a least a little bit,
Carsten

katz wrote:Hi,

The code below almost does what I want it to do. I can get the date and time from an external website (esp8266.com in this case). But I cannot access the local variable 'dtm' outside the function. The last two lines in the code should give the same result, but they don't. Is there a way around this?

Thanks, Peter.

Code: Select allgdtm="xxx"

function getURLdate(url)
   sk=net.createConnection(net.TCP, 0)
   sk:on("receive", function(sck, reply)
      --print(reply)
      i=string.find(reply,"Date: ")
      dtm=string.sub(reply,i+6,i+35)
      _G[gdtm]=dtm     -- make sure that dtm is global
      print("Local date = "..dtm)
      sk:close()
      end )
   sk:send("GET / HTTP/1.1\r\nHost: "..url.."\r\n\r\n")
   sk:connect(80,url)
end

getURLdate("esp8266.com")
print("Global date = "..gdtm)
User avatar
By TerryE
#13493 By the way
Code: Select allgdtm="xxx"
-- ...
 _G[gdtm]=dtm
doesn't set the global variable gdtm, it sets the global variable xxx!! This is because gdtm has the value xxx, and this is therefore equivalent to _G["xxx"]=dtm. What you want here is
Code: Select all_G.gdtm=dtm

Do you understand why?
User avatar
By TerryE
#13496 On separate point, try these two scripts to see that the difference between sync and async scripts is:
Code: Select all-- test2.lua
do
  local a = 10   
  tmr.alarm(1, 1000, 1, function()
    print("Thread A",a); a=a-1; if a==0 then tmr.stop(1) end 
    end)
end
do
  local b = 20
  tmr.alarm(2, 600, 1, function()
    print("Thread B",b); b=b-1; if b==0 then tmr.stop(2) end
    end)
end
--for j=1,10,1 do
--  for i = 1,60000,1 do local j = i*12345 end
--  print "======"; tmr.wdclr()
--end

If you dofile this you will get the two timers firing interleaved. Now try uncommenting the last four lines. You will see that the two threads now block until the foreground loop completes. This is because async triggers will only fire in this lua implementation when there isn't a foreground thread running.

If you now comment out the tmr.wdclr(), then the processor with timout and restart. This is because the watchdog fires if you block the async threads by too much processing, and clearing down the watchdog timer prevents this.

Now try adding an extra layer of code:
Code: Select all--test3.lua
dofile("test2.lua")
local a = 5   
tmr.alarm(3, 3000, 1, function()
    collectgarbage()
    print("Thread C",node.heap()); a=a-1
  if a==0 then tmr.stop(3) end 
  end)
tmr.alarm(4, 12000, 0, function()
--   local dummy = function() end
    local dummy = tmr.now
    collectgarbage()
    print("Thread D first",node.heap()); a=a-1
    tmr.alarm(1, 100, 1, dummy)
    collectgarbage()
    print("Thread D second",node.heap()); a=a-1
    tmr.alarm(2, 100, 1, dummy)
    collectgarbage()
    print("Thread D third",node.heap()); a=a-1
    tmr.alarm(3, 100, 1, dummy)
    collectgarbage()
    print("Thread D last",node.heap()); a=a-1
  end)

This adds a third timer to fire as this proceeds and monitor the heap usage. So what does the timer 4 code show and why does doing this free up memory? The compiled code for the timer 1 function is kept in the heap until every reference to it has been removed and then this code space can be reclaimed for other use. This function is linked to two references: i) the hidden "closure" reference in the compiled test2.lua code, and (ii) the timer control block inside the timer package. (i) is removed when the execution from test2 returns, but the timer control block still includes a reference, so overwriting this with tmr.now() cuts this last link and the garbage collector can now sweep away the dead code.

Ditto for timer 2 and 3. Don't worry if this gives you brain ache, because this gives me brain ache as well and I've been playing with these type of runtime systems for over a decade.