Lua开关程序有个场景无法重连上服务器

作者:candylie520 | 更新时间:2019-09-14

github上的程序我就不贴了, 先说现象

问题一:断开路由器后重连不上路由器的问题,

init.lua程序里面的问题就是, 没有自动重连, 所以当板子连接到wifi获取到ip后, 主动关闭路由器, 再打开路由器就连不上wifi了, 这个解决办法是加一句 

wifi.sta.autoconnect(1)

这样每次断开路由器后就能重新连接上路由器了

 

问题二:先上git上贝壳的主程序

--use sjson

_G.cjson = sjson

--modify DEVICEID INPUTID APIKEY

DEVICEID = "458"

APIKEY = "9cb78xxx9"

INPUTID = "36"

host = host or "www.bigiot.net"

port = port or 8181

LED = 5

isConnect = false

gpio.mode(LED,gpio.OUTPUT)

local function run()

local cu = net.createConnection(net.TCP)

cu:on("receive", function(cu, c)

print(c)

isConnect = true

r = cjson.decode(c)

if r.M == "say" then

if r.C == "play" then

gpio.write(LED, gpio.HIGH)

ok, played = pcall(cjson.encode, {M="say",ID=r.ID,C="LED turn on!"})

cu:send( played.."\n" )

end

if r.C == "stop" then

gpio.write(LED, gpio.LOW)

ok, stoped = pcall(cjson.encode, {M="say",ID=r.ID,C="LED turn off!"})

cu:send( stoped.."\n" )

end

end

end)

cu:on('disconnection',function(scu)

cu = nil

isConnect = false

--停止心跳包发送定时器,5秒后重试

tmr.stop(1)

tmr.alarm(6, 5000, 0, run)

end)

cu:connect(port, host)

ok, s = pcall(cjson.encode, {M="checkin",ID=DEVICEID,K=APIKEY})

if ok then

print(s)

else

print("failed to encode!")

end

if isConnect then

cu:send(s.."\n")

end

tmr.alarm(1, 60000, 1, function()

if isConnect then

cu:send(s.."\n")

end

end)

end

run()

 

在kaiguan.lua程序中,如果路由器关了, 会走disconnection回调, 然后重新执行run方法, 但是此时路由器还没有开启, 那么程序最底下的定时器1就永远也发不出心跳包, 当然也会重连不上服务器了....

所以为了解决这个问题, 我改了下代码, 添加了一个看门的狗子

改动后的代码如下:

--use sjson

_G.cjson = sjson

--modify DEVICEID INPUTID APIKEY

DEVICEID = "1"

APIKEY = "11111111"

INPUTID = "36"

--host = host or "www.bigiot.net"

host = host or "121.42.180.30"

port = port or 8181

LED = 5

isConnect = false

 

gpio.mode(LED,gpio.OUTPUT)

local _Me = {}

autoTime = 1000

hadCloseRoter = false

count = 1

function watch()

--此定时间用来判断ip是否被中断过,因为当直接路由器断电后, wifi会自动连接,但是不会走自动登录服务器,

tmr.alarm(2, autoTime, 1, function()

print("zk,"..count)

count = count+1

if wifi.sta.getip() == nil then

--记录已经有过wifi断线 那就把循环次数调低到1分钟检测一次ip是否有获取到

autoTime = 6000

--关闭定时器节约资源

tmr.stop(1)

--如果是首次记录到断线,就重新按照新时间记录定时器

if hadCloseRoter == false then

tmr.stop(2)

--记录下已经有过断开wifi的记录

hadCloseRoter = true

print("dog watch Time set 6s once")

watch()

end

else

--如果记录过有wifi断线 并且当前ip已经获取到了,连上了路由器,就重新走run方法

if hadCloseRoter then

print("check had close wifi link, now need auto link service,and dog watch time set 1s once")

isConnect = false

hadCloseRoter = false

autoTime = 1000

tmr.stop(1)

tmr.stop(2)

cu = nil

watch()

run()

end

end

end)

end

watch()

 

function run()

--获取cu

local cu = net.createConnection(net.TCP)

--收到服务器消息的回调

cu:on("receive", function(cu, c)

print("zk,receive\n")

print(c)

isConnect = true

r = cjson.decode(c)

if r.M == "say" then

if r.C == "play" then

gpio.write(LED, gpio.HIGH)

ok, played = pcall(cjson.encode, {M="say",ID=r.ID,C="LED turn on!"})

cu:send( played.."\n" )

end

if r.C == "stop" then

gpio.write(LED, gpio.LOW)

ok, stoped = pcall(cjson.encode, {M="say",ID=r.ID,C="LED turn off!"})

cu:send( stoped.."\n" )

end

end

end)

--服务器断开连接的回调 如果是直接路由器断电会走此方法, 但是路由器的wlan断了不会走此方法

cu:on('disconnection',function(scu)

cu = nil

isConnect = false

--停止心跳包发送定时器,5秒后重试

print("zk,disconnection")

tmr.stop(1)

tmr.alarm(6, 3000, 0, run)

end)

--连接服务器 连接成功后会在Reciver中返回:{"M":"WELCOME TO BIGIOT"} 并且isConnet设置为true

cu:connect(port, host)

 

--encode密钥ID

ok, s = pcall(cjson.encode, {M="checkin",ID=DEVICEID,K=APIKEY})

--如果密钥ID正常就 打印密钥ID

if ok then

print(s)

else

print("failed to encode!")

end

 

--发送心跳

if isConnect then

cu:send(s.."\n")

end

 

--启动5s定时器 如果已连接就定时发送心跳

tmr.alarm(1, 8000, 1, function()

if isConnect then

print("auto send headPackge")

cu:send(s.."\n")

else

print("not connected ...")

end

end)

end

run()

添加了一个定时器的方法, 由于一点不懂lua还有nodemcu的api, 就这样搞了下, 核心逻辑是这样的:

连上网后每秒钟检测ip, 如果检测到ip为空了就把这个定时器的时间改成每6s运行一次查询ip, 如果检测到ip又获取到了,表示重连上了路由器, 这时候就再次把这个定时器的时间改为1s一次, 

并且重新执行run方法, 所以 现在问题2就已经改好了, 每次被断开wifi后, 重连上了就能主动连接贝壳服务器了, 但是这样还是有问题......

 

问题三: 当脸上贝壳后台后, 路由器的网断了, 这时候虽然板子连上了路由器, 也一直在执行定时器1的心跳包, 但是,这种情况是不会走disconnection回调的,

所以造成的现象就是板子并不知道自己已经没有外网了,还一直以为自己在线, 不断地发心跳包, 这是没什么卵用的,  这时候, 当路由器又连接到了外网后, 板子还是处于蒙蔽状态

还是以为自己在线, 也收不到disconnection回调改变自己状态, 贝壳的服务器也是检测不到设备在线的

 

由于就昨天晚上研究下了lua, 还不是很懂, 所以问题3无法搞定,  目前就是 只要解决了路由器的wlan掉线后, 板子能知道自己掉线了, 然后等路由器的wlan外网连接好后板子能主动重连服务器 ,那这个程序就算完整了,

然后在环境中遇到各种现象应该都能自动的上线了... 有没有大神知道这个问题怎么搞定, 贴个代码看看怎么弄

 

 

 


评论:共1条

caibihui163 评论于:2019-09-23 16:58:36
发送心跳包后,贝壳服务器应有一个 响应的回复,检测这个有没有回复就可以知其有没有接上贝壳了?个人观点,我没有具体看过!
评论支持使用[code][/code]标签添加代码
返回顶部