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

User avatar
By StefanL38
#69982 Hi,

recently I encountered code-crashing and rebooting of my ESP8266-module with code that should do data-exchange between two ESP8266-modules.

I started with some TCP-server and client-code you can find in the web on several places.
These Lua-codes do work as a demo-example.

I sended back and forth some dozen characters between server and client but after 300 up to 1500 loops the code crashed with an error-message PANIC: unprotected error in call to Lua API: not connected

So can anybody show me how to code consequently in an eventdriven stile to avoid PANIC-crashing?
please do NOT post links to "basic TCP-server-codes. These are the codes I have used and that lead to the crashing if you want to use it for more than one minute of testing.

My main goal is to exchange some hundred bytes between several ESP8266-modules over WiFi
If somebody has other ideas how this data-exchange can be realised (like using UDP instead of TCP etc.)

I'm opened to these other approaches.

I will share my on experience and code-improvements about this here in this forum.

best regards

Stefan
User avatar
By StefanL38
#69988 hello Marcel,

thank you very much for answering and asking for more infos.

Hm - I don't know. My code sends a "Hello World" message every two seconds. The PANIC crash occurs after 300 up to 1500 loops which equals with 300*2/60 = 10 minutes up to 1500*2/60 = 50 minutes.

client-code
Code: Select all          cl=net.createConnection(net.TCP, 0)
          cl:connect(80,"192.168.4.1")


server-code
Code: Select allsv = net.createServer(net.TCP)
sv:listen(80, function(conn)
    conn:on("receive", function(conn, receivedData)
        print(MyIDString.."Rcv Data:#" .. receivedData.."#")         
    end)


If client and server are setup this way does the DHCP-lease expire after 10 to 50 minutes?

I guess my rudimentary knowledge about how to code in Lua reliable lead me to some "crappy" code that might cause the error. That is the reason why I asked for example -code

here is the complete code
client
Code: Select all--
MyIDString = " ESP8266_Client4.lua "
station_cfg={}
station_cfg.ssid="test"
station_cfg.pwd="12345678"

print(MyIDString)
wifi.sta.disconnect()
wifi.setmode(wifi.STATION)
wifi.sta.config(station_cfg)
wifi.sta.connect()
print("Looking for a connection")

tmr.alarm(1, 2000, 1, function()
     if(wifi.sta.getip()~=nil) then
          tmr.stop(1)
          ConnectErrorCnt = 0
          LoopCnt = 0
          print("Connected!")
          print("Client IP Address:",wifi.sta.getip())
          cl=net.createConnection(net.TCP, 0)
          cl:connect(80,"192.168.4.1")
          cl:on("receive", function(cl, pl) print(pl) end)
          tmr.alarm(2, 1000, 1, function()
              WiFiStatus = wifi.sta.status()
              print("ConnErrCnt:"..ConnectErrorCnt)
              print(MyIDString.."direct before sended Hello World to server 192.168.4.1") 
              if wifi.sta.status() == wifi.STA_GOTIP then
                print("wifi.sta.status()"..wifi.sta.status()) 
                cl:send(MyIDString.."Hello World! wifi.sta.status()"..wifi.sta.status())
                LoopCnt = LoopCnt + 1
                print(MyIDString.."direct after sended Hello World LoopCn:t"..LoopCnt) 
              else 
                ConnectErrorCnt = ConnectErrorCnt + 1
                print(MyIDString.."WiFiStatus <> wifi.STA_GOTIP: "..WiFiStatus)
                print("wifi.STA_IDLE="..wifi.STA_IDLE)
                print("wifi.STA_CONNECTING="..wifi.STA_CONNECTING)
                print("wifi.STA_WRONGPWD="..wifi.STA_WRONGPWD)
                print("wifi.STA_APNOTFOUND="..wifi.STA_APNOTFOUND)
                print("wifi.STA_FAIL="..wifi.STA_FAIL)
                print("wifi.STA_GOTIP="..wifi.STA_GOTIP)
              end 
          end)
      else
         print("Connecting...")
      end
end)


server-code
Code: Select allwifi.eventmon.register(wifi.eventmon.STA_CONNECTED, function(T)
 print("\n\tSTA - CONNECTED".."\n\tSSID: "..T.SSID.."\n\tBSSID: "..
 T.BSSID.."\n\tChannel: "..T.channel)
 end)

 wifi.eventmon.register(wifi.eventmon.STA_DISCONNECTED, function(T)
 print("\n\tSTA - DISCONNECTED".."\n\tSSID: "..T.SSID.."\n\tBSSID: "..
 T.BSSID.."\n\treason: "..T.reason)
 end)

 wifi.eventmon.register(wifi.eventmon.STA_AUTHMODE_CHANGE, function(T)
 print("\n\tSTA - AUTHMODE CHANGE".."\n\told_auth_mode: "..
 T.old_auth_mode.."\n\tnew_auth_mode: "..T.new_auth_mode)
 end)

 wifi.eventmon.register(wifi.eventmon.STA_GOT_IP, function(T)
 print("\n\tSTA - GOT IP".."\n\tStation IP: "..T.IP.."\n\tSubnet mask: "..
 T.netmask.."\n\tGateway IP: "..T.gateway)
 end)

 wifi.eventmon.register(wifi.eventmon.STA_DHCP_TIMEOUT, function()
 print("\n\tSTA - DHCP TIMEOUT")
 end)

 wifi.eventmon.register(wifi.eventmon.AP_STACONNECTED, function(T)
 print("\n\tAP - STATION CONNECTED".."\n\tMAC of client: "..T.MAC.."\n\tAID: "..T.AID)
 table={}
   table=wifi.ap.getclient()
   for mac,ip in pairs(table) do
     print(mac,ip)
   end             
 
 end)

 wifi.eventmon.register(wifi.eventmon.AP_STADISCONNECTED, function(T)
 print("\n\tAP - STATION DISCONNECTED".."\n\tMAC: "..T.MAC.."\n\tAID: "..T.AID)
 end)

MyIDString = " ESP8266_Server3.lua "
 
print(MyIDString)
wifi.setmode(wifi.STATIONAP);
wifi.ap.config({ssid="test",pwd="12345678"});
print("Server IP Address:",wifi.ap.getip())

sv = net.createServer(net.TCP)
sv:listen(80, function(conn)
    conn:on("receive", function(conn, receivedData)
        print(MyIDString.."Rcv Data:#" .. receivedData.."#")         
    end)

    tmr.alarm(1, 10000, 1, function()
        if wifi.sta.getip()== nil then
            print("Waiting for IP...")
        else
            WiFiStatus = wifi.sta.status()
            if WiFiStatus == wifi.STA_GOTIP then
              table={}
              table=wifi.ap.getclient()
              for mac,ip in pairs(table) do
                print(mac,ip)
              end             
              print(MyIDString.."send Msg Hi to client")
              conn:send(MyIDString.."Server to Client Hi Client")
              print(MyIDString.."Msg Hi sended to client")
              table={}
              table=wifi.ap.getclient()
              for mac,ip in pairs(table) do
                print(mac,ip)
              end             
            else 
              print(MyIDString.."Wifi-Status: "..WiFiStatus)
            end 
        end
end)

end)


if you think this amount of code is bloating the thread I can delete it again

best regards

Stefan
User avatar
By marcelstoer
#69989 I see that Terry already gave you hints over at https://github.com/nodemcu/nodemcu-firmware/issues/2102. Upon seeing your code it's clear that "not connected" is refers to the socket not being connected and not the WiFi connection.

As Terry said you shouldn't reuse the socket connection in the timer and handle callbacks properly. For starters I would

  • Move the 'cl' creation inside the 'tmr.alarm(2, 1000, 1, function()'
  • Set up the event handlers (on-receive) for 'cl' before you call 'connect'
  • Do not (re-)use the 'cl' variable inside the callback functions, this will lead to memory leaks
  • Close the socket when you're done sending

The relevant examples to study are https://nodemcu.readthedocs.io/en/lates ... #example_5 and the sending part of https://nodemcu.readthedocs.io/en/lates ... #example_6.

As for posting (long pieces) code I advise you always strip examples to the bare minimum. It helps people help you. Long and bloated code examples usually stop me from even looking into an issue.