NodeMCU boilerplate – multiple WiFi credentials

In parameters.lua we may set only one access point and a password. But lately, I’m testing my devices in different areas, different APs. Changing passwords all the time is stupid so we need to improve this.

We will allow the table of credentials and boilerplate will iterate over them to get the connection.

Planing

In current wifi-init.lua we are using old timers. So it is time for full refactor!

One is used during boot and checks each 2s if we have a valid connection. If the connection is established it runs main.lua and starts the second timer.
Second timer checks if the connection is alive. If it detects a fail, it increases a counter. After reaching 10 it reboots the node.

Now we need a different approach. We have a list of APs and passwords. Script tries to connect to the first one and if fails 5 times it goes to the next one. This is the boot routine.
What about keep-alive checks?
The timer should check like the old one, in the case of 10 failures reboot the node.

WiFi at boot

We need to have a table with access points and passwords. This configuration goes to parameter.lua:

_WIFI_APS = {
    {["bubus"]="whoknowsme"},
    {["bubus1"]="whoknowsme1"},
    {["correct_ap"]="correct_passwd"},
}

To keep track which is an active pair we will use a variable _WIFI_CURRENT_AP.  Defaults to one.
Before we start a timer we need to prepare a few things:

_WIFI_CURRENT_AP = 1
_WIFI_FAIL_COUNTER = 0
wifi.setmode(wifi.STATION)
NET_AP,NET_PASSWORD =  next(_WIFI_APS[_WIFI_CURRENT_AP])
wifi.sta.config(NET_AP, NET_PASSWORD)

And a new timer for connection during boot:

if wifi.sta.getip() == nil then
    local _boot_wifi_counter = 0
    local _boot_wifi_timer = tmr.create()
    _boot_wifi_timer:alarm(2000, tmr.ALARM_AUTO, function()
        if _boot_wifi_counter == 0 then
            NET_AP,NET_PASSWORD =  next(_WIFI_APS[_WIFI_CURRENT_AP])
            wifi.sta.config(NET_AP, NET_PASSWORD)
            print("Connecting to: "..NET_AP)
        end
        if wifi.sta.getip() == nil then     
            print(" Wait for IP --> "..wifi.sta.status()) 
            _boot_wifi_counter = _boot_wifi_counter + 1
            if _boot_wifi_counter == 6 then
                _boot_wifi_counter = 0
                _WIFI_CURRENT_AP = _WIFI_CURRENT_AP + 1
                if _WIFI_CURRENT_AP > #_WIFI_APS then
                    _WIFI_CURRENT_AP = 1
                end
             end   
        else             
            _boot_wifi_timer:stop()
            if file.exists('main.lc') then  
                dofile("main.lc")        
            else
                dofile("main.lua")        
            end
        end

    end)
end

This is a big stack of ifs:)

Let’s write a keep-alive timer:

_wifi_keepalive_timer = tmr.create()
_wifi_keepalive_timer:register(5000, tmr.ALARM_AUTO, function()
    if wifi.sta.status() ~= 5 then
        _WIFI_FAIL_COUNTER = _WIFI_FAIL_COUNTER + 1
        print ("WiFi fail: "..wifi.sta.status())
    else
        WIFI_FAIL_COUNTER = 0
    end
    if WIFI_FAIL_COUNTER > 10 then        
        print "Node reboot..."
        node.restart()
    end       
end)

It is the same functionality as in the previous version. Only the timer was changed from numeric to object.

Summary

This is a small but important change. Setting multiple APs makes my live easier. I can fully prepare a device at home, take it to work and just plug.
And I’m quite angry at manual updates, maybe it is a time for OTA module?

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s