Skip to content

Commit

Permalink
Merge pull request #36 from konnected-io/wifi-disconnect-fix
Browse files Browse the repository at this point in the history
improve wifi disconnect logic
  • Loading branch information
heythisisnate authored Aug 15, 2017
2 parents e0168c2 + 532c895 commit f2802d9
Show file tree
Hide file tree
Showing 6 changed files with 318 additions and 28 deletions.
161 changes: 161 additions & 0 deletions spec/init_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
describe("init", function()
local mock_timer

before_each(function()
mock(_G.enduser_setup)
mock_timer = mock({
register = function() end,
alarm = function() end,
unregister = function() end,
start = function() end
})
end)

describe("when wifi is not configured yet", function()
before_each(function()
require("spec/nodemcu_stubs")
nodemcu.wifi.sta.config = ""
mock(_G.enduser_setup)

dofile("src/init.lua")
end)

after_each(function()
nodemcu.wifi.sta.config = { ssid = 'test' }
end)

it("starts enduser_setup", function()
assert.spy(_G.enduser_setup.manual).was.called_with(false)
assert.spy(_G.enduser_setup.start).was.called()
end)
end)

describe("tmr: poll for IP address", function()

before_each(function()
require("spec/nodemcu_stubs")
stub(_G.tmr, 'create').returns(mock_timer)
dofile("src/init.lua")

spy.on(_G.gpio, 'write')
spy.on(wifi.eventmon, 'unregister')
end)

describe("when there's no IP address", function()
before_each(function()
nodemcu.run_tmr(900, tmr.ALARM_AUTO)
end)

it("does not stop enduser_setup", function()
assert.spy(_G.enduser_setup.stop).was_not.called()
end)
end)

describe("when there's an IP address", function()
before_each(function()
nodemcu.wifi.sta.ip = '192.168.1.100'
nodemcu.run_tmr(900, tmr.ALARM_AUTO)
end)

it("stops enduser_setup", function()
assert.spy(_G.enduser_setup.stop).was.called()
end)

it("turns off the led", function()
assert.spy(_G.gpio.write).was.called_with(4, _G.gpio.HIGH)
end)

it("unregisters the failsafeTimer and wifiFailTimer", function()
assert.stub(mock_timer.unregister).was.called()
assert.are.equal(#mock_timer.unregister.calls, 2) -- wifiFailTimer and failSafeTimer
end)

it("unregisters the wifi disconnect eventmon", function()
assert.spy(wifi.eventmon.unregister).was.called_with(wifi.eventmon.STA_DISCONNECTED)
end)
end)

end)

describe("when receiving a disconnect signal", function()
before_each(function()
require("spec/nodemcu_stubs")
stub(_G.tmr, 'create').returns(mock_timer)
dofile("src/init.lua")
spy.on(wifi.eventmon, 'unregister')

nodemcu.wifi.eventmon['STA_DISCONNECTED']({SSID = "test", BSSID = "test", reason = "201"})
end)

it("starts the wifiFailTimer", function()
assert.stub(mock_timer.start).was.called()
end)

describe("after failing the wifiFailTimer", function()
before_each(function()
nodemcu.run_tmr(30000, tmr.ALARM_SINGLE)
end)

it("starts wifi setup", function()
assert.spy(_G.enduser_setup.manual).was.called_with(false)
assert.spy(_G.enduser_setup.start).was.called()
end)

it("starts the failsafeTimer", function()
assert.stub(mock_timer.start).was.called()
end)

it("unregisters the wifi disconnect eventmon", function()
assert.spy(wifi.eventmon.unregister).was.called_with(wifi.eventmon.STA_DISCONNECTED)
end)

it("unregisters the wifiFailTimer", function()
assert.stub(mock_timer.unregister).was.called()
assert.are.equal(#mock_timer.unregister.calls, 1)
end)

describe("after failing the failsafeTimer", function()
before_each(function()
spy.on(node, 'restart')
nodemcu.run_tmr(300000, tmr.ALARM_SINGLE)
end)

it("restarts", function()
assert.spy(node.restart).was.called()
end)
end)

describe("after connecting", function()
before_each(function()
nodemcu.wifi.sta.ip = '192.168.1.100'
nodemcu.run_tmr(900, tmr.ALARM_AUTO)
end)

it("it stops the wifiFailTimer and failSafeTimer", function()
assert.stub(mock_timer.unregister).was.called()
assert.are.equal(#mock_timer.unregister.calls, 2) -- wifiFailTimer and failSafeTimer
end)

it("unregisters the wifi disconnect eventmon", function()
assert.spy(wifi.eventmon.unregister).was.called_with(wifi.eventmon.STA_DISCONNECTED)
end)
end)
end)

describe("after connecting", function()
before_each(function()
nodemcu.wifi.sta.ip = '192.168.1.100'
nodemcu.run_tmr(900, tmr.ALARM_AUTO)
end)

it("it stops the wifiFailTimer and failSafeTimer", function()
assert.stub(mock_timer.unregister).was.called()
assert.are.equal(#mock_timer.unregister.calls, 2) -- wifiFailTimer and failSafeTimer
end)

it("unregisters the wifi disconnect eventmon", function()
assert.spy(wifi.eventmon.unregister).was.called_with(wifi.eventmon.STA_DISCONNECTED)
end)
end)
end)
end)
113 changes: 111 additions & 2 deletions spec/nodemcu_stubs.lua
Original file line number Diff line number Diff line change
@@ -1,7 +1,116 @@
nodemcu = {
tmrs = {},
run_tmr = function(interval, type)
for _,v in pairs(nodemcu.tmrs) do
if v.interval == interval and v.type == type then
print('Running tmr ' .. type .. ', interval:', interval )
return v.fn({unregister = function() end})
end
end
end,
wifi = {
eventmon = {},
sta = {
config = { ssid = 'test' },
ip = nil
}
}
}

_G.node = {
heap = function() return(0) end
heap = function() return 0 end,
chipid = function() return 0 end,
restart = function() end
}

_G.tmr = {
ALARM_SINGLE = 'ALARM_SINGLE',
ALARM_AUTO = 'ALARM_AUTO',
ALARM_SEMI= 'ALARM_SEMI',
create = function()
return {
alarm = function(_, interval, type, fn)
table.insert(nodemcu.tmrs, {
interval = interval,
type = type,
fn = fn
})
end,
register = function(_, interval, type, fn)
table.insert(nodemcu.tmrs, {
interval = interval,
type = type,
fn = fn
})
end,
unregister = function() end,
start = function() end
}
end
}

_G.file = {
list = function() return {} end,
exists = function() end
}

_G.gpio = {
HIGH = 'HIGH',
LOW = 'LOW',
mode = function() end,
read = function() end,
write = function() end
}

_G.wifi = {
eventmon = {
STA_DISCONNECTED = 'STA_DISCONNECTED',
register = function(key, fn)
print(key)
nodemcu.wifi.eventmon[key] = fn
end,
unregister = function(key)
nodemcu.wifi.eventmon[key] = nil
end,
reason = {
AUTH_EXPIRE = 2
}
},

sta = {
getip = function() return nodemcu.wifi.sta.ip end,
getconfig = function() return nodemcu.wifi.sta.config end,
getmac = function() return 'aa:bb:cc:dd:ee:ff' end
}
}

_G.enduser_setup = {
start = function() end,
stop = function() end,
manual = function() end
}

_G.net = {
multicastJoin = function() end,
createServer = function()
return {
listen = function() end,
on = function() end
}
end
}

}
-- Print contents of `tbl`, with indentation.
-- `indent` sets the initial level of indentation.
function tprint (tbl, indent)
if not indent then indent = 0 end
for k, v in pairs(tbl) do
formatting = string.rep(" ", indent) .. k .. ": "
if type(v) == "table" then
print(formatting)
tprint(v, indent+1)
else
print(formatting .. tostring(v))
end
end
end
2 changes: 1 addition & 1 deletion src/application.lua
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ sendTimer:alarm(200, tmr.ALARM_AUTO, function(t)
local sensor = sensors[sensorSend[1]]
timeout:start()
http.put(
table.concat({ smartthings.apiUrl, "\/device\/", dni, "\/", sensor.pin, "\/", gpio.read(sensor.pin) }),
table.concat({ smartthings.apiUrl, "/device/", dni, "/", sensor.pin, "/", gpio.read(sensor.pin) }),
table.concat({ "Authorization: Bearer ", smartthings.token, "\r\n" }),
"",
function(code)
Expand Down
2 changes: 1 addition & 1 deletion src/device.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
local me = {
name = "Security",
hwVersion = "2.0.0",
swVersion = "2.0.2"
swVersion = "2.0.3"
}
return me
60 changes: 40 additions & 20 deletions src/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,65 @@ print("Heap: ", node.heap(), "Initializing device")
require("start")
print("Heap: ", node.heap(), "Loaded: ", "Startup (compiler & blinker)")
print("Heap: ", node.heap(), "Connecting to Wifi..")
local startCountDown = 0

wifi.eventmon.register(wifi.eventmon.STA_DISCONNECTED, function(T)
print("Heap: ", node.heap(), "Cannot connect to WiFi:", T.SSID, T.BSSID, T.reason)
local startWifiSetup = function()
print("Heap: ", node.heap(), "Entering Wifi setup mode")
wifi.eventmon.unregister(wifi.eventmon.STA_DISCONNECTED)
wifiFailTimer:unregister()
wifiFailTimer = nil
enduser_setup.manual(false)
enduser_setup.start()
wifi.eventmon.unregister(wifi.eventmon.STA_DISCONNECTED)
print("Heap: ", node.heap(), "WiFi Setup started")
failsafeTimer:start()
end

-- wait 30 seconds before entering wifi setup mode in case of a momentary outage
wifiFailTimer = tmr.create()
wifiFailTimer:register(30000, tmr.ALARM_SINGLE, function() startWifiSetup() end)

-- failsafe: reboot after 5 minutes in case of extended wifi outage
failsafeTimer = tmr.create()
failsafeTimer:register(300000, tmr.ALARM_SINGLE, function() node.restart() end)

wifi.eventmon.register(wifi.eventmon.STA_DISCONNECTED, function(T)
print("Heap: ", node.heap(), "Cannot connect to WiFi ", T.SSID, 'Reason Code:', T.reason)

if T.reason == wifi.eventmon.reason.AUTH_EXPIRE then
-- wifi password is incorrect, immediatly enter setup mode
print("Heap: ", node.heap(), "Wifi password is incorrect")
startWifiSetup()
else
wifiFailTimer:start()
end
end)

if wifi.sta.getconfig() == "" then
print("Heap: ", node.heap(), "WiFi not configured")
startCountDown = 5
enduser_setup.manual(false)
enduser_setup.start()
startWifiSetup()
print("Heap: ", node.heap(), "WiFi Setup started")
end

local _ = tmr.create():alarm(900, tmr.ALARM_AUTO, function(t)
require("led_flip").flip()
if wifi.sta.getip() then
wifi.eventmon.unregister(wifi.eventmon.STA_DISCONNECTED)
t:unregister()
t = nil
if wifiFailTimer then
wifiFailTimer:unregister()
wifiFailTimer = nil
end
failsafeTimer:unregister()
failsafeTimer = nil
print("Heap: ", node.heap(), "Wifi connected with IP: ", wifi.sta.getip())
if file.exists("update_init.lc")then
require("update")
else
if startCountDown > 1 then
startCountDown = startCountDown - 1
else
startCountDown = nil
gpio.write(4, gpio.HIGH)
enduser_setup.stop()
wifi.eventmon.unregister(wifi.eventmon.STA_DISCONNECTED)
require("server")
print("Heap: ", node.heap(), "Loaded: ", "server")
require("application")
print("Heap: ", node.heap(), "Loaded: ", "application")
end
gpio.write(4, gpio.HIGH)
enduser_setup.stop()
require("server")
print("Heap: ", node.heap(), "Loaded: ", "server")
require("application")
print("Heap: ", node.heap(), "Loaded: ", "application")
end
end
end)
Expand Down
Loading

0 comments on commit f2802d9

Please sign in to comment.