Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

network

NetworkManager: connectivity, Wi-Fi and wired state, scanned access points and join progress.

text {
    content = mantle.network:map(function(network)
        if network == nil then
            return ""
        elseif not network.connected then
            return "offline"
        elseif network.ssid == "Ethernet" then
            return "wired"
        end
        return string.format("%s %d%%", network.ssid or "", network.strength)
    end),
}

State

mantle.network:get() returns NetworkState, nil before the first push. A field marked ? may be absent.

mantle.network’s payload.

FieldTypeDescription
available_networksAccessPointInfo[]NetworkManager’s visible networks, re-read on every change: one per SSID, at most 20, ordered associated, then saved, then strongest. {} without Wi-Fi hardware.
connect_error?JoinErrorThe last failed connect, or nil before any or after a success. Kept until the next connect, cancel_connect or abort_connect; check its ssid before showing it.
connectedbooleanA connection carries the default route; false means offline.
connecting_ssid?stringThe SSID connect is joining, or nil; clears on a verdict or abort_connect.
ethernet_enabledbooleanA wired device is activated; set_ethernet_enabled’s read-back, unlike carrier.
ethernet_ip?stringThe first activated wired device’s IPv4 address without prefix, or nil.
ethernet_presentbooleanAt least one wired device exists, cable or not.
ethernet_speedintegerThat wired device’s link speed in Mb/s; 0 when unknown or none is activated.
networking_enabledbooleanNetworkManager networking is on (NetworkingEnabled).
password_ssid?stringThe SSID whose connect waits for a password from a network/connect secure field, or nil. Also set after a rejected key; cleared when a join starts or by cancel_connect.
scanningbooleanA scan is in flight, from the moment scan is accepted.
ssid?string"Ethernet" when the default route is wired, else the associated SSID, else nil. An association still getting an address has an ssid while connected is false.
strengthintegerThe associated network’s strength, 0 to 100; 0 without a Wi-Fi association.
wifi_enabledbooleanWi-Fi radio power (WirelessEnabled); can be true with no Wi-Fi hardware, see wifi_present.
wifi_ip?stringThe Wi-Fi device’s IPv4 address without prefix, or nil.
wifi_presentbooleanA Wi-Fi device exists.

AccessPointInfo

One scanned network in available_networks.

FieldTypeDescription
activebooleanThe Wi-Fi device is associated with this SSID.
bandstring"2.4 GHz", "5 GHz", "6 GHz", or empty for a frequency outside those bands.
savedbooleanA saved NetworkManager profile names this SSID, so connect asks for no password.
securebooleanNeeds a key: WEP, WPA or RSN.
ssidstringNetwork name, "" for hidden networks; one entry per SSID, from its strongest access point.
strengthintegerSignal strength, 0 to 100.

JoinError

A failed join, as connect_error.

FieldTypeDescription
messagestringDisplay text, such as "wrong password" or "network not found".
ssidstringThe network the join was for.

Actions

Call each as mantle.network:<action>(arguments...); ? marks an argument you may omit.

ActionArgumentsDescription
set_networking_enabledenabled: booleanTurns NetworkManager networking on or off.
set_wifi_enabledenabled: booleanPowers the Wi-Fi radio.
set_ethernet_enabledenabled: booleanfalse disconnects every wired device; true activates each one’s autoconnect profile, and a device without one stays down.
scanRequests a Wi-Fi scan; a no-op without Wi-Fi hardware.
connectssid: string, hidden: booleanJoins a network. Without a saved profile, a secured, hidden or out-of-range one sets password_ssid and waits for a key.
cancel_connectDrops the password request password_ssid names; a join already running continues.
abort_connectStops the join connecting_ssid names, deleting a profile the join created.
forgetssid: stringDeletes every saved profile for this SSID.
disconnect_wifiDisconnects Wi-Fi; NetworkManager does not autoconnect it again until the next join.

Backend

ContractBehavior
UpdatesEvery manager, device-list, device-state, access-point, association and saved-profile change re-reads the whole state from NetworkManager. A hotplugged adapter rescans the device set
DevicesOnly the first Wi-Fi device is tracked. Wired fields describe the first activated wired device
TogglesNetworking through Enable, Wi-Fi through WirelessEnabled
ScanRequestScan. scanning turns true on the call and false when LastScan moves or NetworkManager refuses
Access pointsThe associated one’s strength is live. The others’ are read when they appear and after each scan, when NetworkManager updates them
ConnectA saved profile or an open network in range joins at once. Anything else sets password_ssid and waits for the key from a secure_submit = { capability = "network", action = "connect" } field (secure fields); the key never reaches Lua
Join verdictWatched for up to 45 s. A rejected key sets password_ssid again. A new network’s profile, key included, is saved when the join starts and stays after a rejection; a key retyped for a saved profile reaches disk only once NetworkManager accepts it
Abortabort_connect deletes a profile the join created, else deactivates the join
MissingStays nil. The next generation’s first read retries

How do I…

Ask for a Wi-Fi password

Show the field while password_ssid is set. Escape clears a secure field and keeps it armed, then calls its on_cancel, the place to call cancel_connect:

local asking = mantle.network:map(function(network)
    return network ~= nil and network.password_ssid ~= nil
end)

return column {
    visible = asking,
    spacing = 6,
    children = {
        text {
            content = mantle.network:map(function(network)
                return network and network.password_ssid and ("Password for " .. network.password_ssid) or ""
            end),
        },
        textfield {
            width = 240,
            height = 24,
            placeholder = "Password",
            secure_submit = { capability = "network", action = "connect" },
            on_cancel = function() mantle.network:cancel_connect() end,
        },
    },
}

Know whether a join worked

A failed connect lands in connect_error:

text {
    foreground = "#F38BA8",
    content = mantle.network:map(function(network)
        local failure = network and network.connect_error
        return failure and (failure.ssid .. ": " .. failure.message) or ""
    end),
}

Gotchas

TrapFix
available_networks has a row with ssid == ""Hidden networks broadcast no name; they merge into one nameless row. Skip it and join hidden networks with connect(ssid, true)
A hidden network asks for a password even when openIts security is unknown until it answers. Enter on the empty field joins it as open

Source: supervisor/src/capabilities/network/