Failover for wifi connections

Hi Balena community,

what is the recommended way to handle failover for wifi connections and network prioritisation within balena.

Environment:
I currently have two independent WiFi hotspots using different celular carriers in a remote location with multiple balena device connected to them. Lets suppose 20 devices are in reach of these two connections.

Problem
I would like to setup these devices in a way, that half of them (10 devices) will connect to one WiFi access point and the other half to the other one. Only if one wifi connection is not available or the internet connection is not stable, they should connect to the other access point as a fail over.

What is the most balena way to handle the problem?

Ideas:

My current approach would be to handle this manually in the code and set the dbus NetoworkManager settings. But this appears to be a bit hacky. Do you have other ideas on how to solve this?

Hey there, I think using D-Bus to create NetworkManager profiles via your app is the way to go, but you don’t need a ton of special logic to assign a priority to interfaces. By using autoconnect-priority and autoconnect=true on two connections the NetworkManager should be able to handle the rest. Just set 10 of your devices to prefer one interface over the other, maybe based on an environment variable set via the Dashboard?

Here’s another forum link where a user accomplished a similar thing:

1 Like

Thank you @klutchell this appears to be a the way to go. Furthermore the autoconnect=true hint, will probably save me a lot of time.

Let us know how it works out!

Just as an update, i decided to go the dbus way, since i needed to switch the settings while the device is running.

Wifi = namedtuple(
    'Wifi', ['ssid', 'password', 'autoconnect_priority']
)

def add_wifi_credentials(
    wifi: tuple = DEFAULT_WIFI
):
    dbus_connection_dict = {
        'type': '802-11-wireless',
        'uuid': str(uuid.uuid4()),
        'id': wifi.ssid
    }
    if wifi.autoconnect_priority:
        dbus_connection_dict['autoconnect-priority'] = \
            wifi.autoconnect_priority
        dbus_connection_dict['autoconnect'] = True

    s_con = dbus.Dictionary(dbus_connection_dict)

    s_wifi = dbus.Dictionary({
        'ssid': dbus.ByteArray(wifi.ssid.encode('utf8')),
        'mode': 'infrastructure',
        'hidden': dbus.Boolean(True),
    })

    s_wsec = dbus.Dictionary({
        'key-mgmt': 'wpa-psk',
        'auth-alg': 'open',
        'psk': wifi.password,
    })

    s_ip4 = dbus.Dictionary({'method': 'auto'})
    s_ip6 = dbus.Dictionary({'method': 'auto'})

    con = dbus.Dictionary({
        'connection': s_con,
        '802-11-wireless': s_wifi,
        '802-11-wireless-security': s_wsec,
        'ipv4': s_ip4,
        'ipv6': s_ip6,
    })

    bus = dbus.SystemBus()

    proxy = bus.get_object(
        "org.freedesktop.NetworkManager",
        "/org/freedesktop/NetworkManager/Settings"
    )
    settings = dbus.Interface(
        proxy,
        "org.freedesktop.NetworkManager.Settings"
    )
    settings.AddConnection(con)
    return True