# `network`

The network, followed live: from NetworkManager, or from iwd
(`net.connman.iwd`) where NetworkManager does not run. Either one
starting or stopping switches to the other. `network.disconnect()`
leaves the Wi-Fi network joined, and `network.scan()` scans for
networks now.

| Field | Type | |
| --- | --- | --- |
| `connected` | `bool` | A network connection is up. Over iwd, which knows only Wi-Fi: the Wi-Fi network is joined. |
| `ssid` | `text?` | The Wi-Fi network joined, if any. |
| `strength` | `float` | The Wi-Fi signal strength, 0 to 1. |
| `wifi` | `bool rw` | The Wi-Fi radio is on. Writable. |
| `access_points` | `[AccessPoint]` | The Wi-Fi networks in range, keyed by `ssid`. Scanned only while a visible reader reads them (a network menu that is open). |
| `available` | `bool` | NetworkManager or iwd answers: false without either (or without a system bus), so a menu can hide what cannot work. |
| `connecting` | `text?` | The Wi-Fi network being joined, by name: from the moment `ap.connect()` or `ap.connect_with()` is asked, or the daemon starts joining one on its own, until it is joined or fails; null otherwise (`if network.connecting == ap.ssid { … }`). |
| `disconnecting` | `text?` | The Wi-Fi network being left (`network.disconnect()`, or the daemon leaving it), until it is left; null otherwise. |
| `frequency` | `int?` | The joined Wi-Fi network's frequency in MHz (2412, 5180, 5955): below 3000 is the 2.4 GHz band, 5150 to 5895 the 5 GHz band, from 5925 the 6 GHz band. Null while no Wi-Fi network is joined, or when iwd does not say. |
| `security` | `WifiSecurity?` | How the joined Wi-Fi network is secured; null while none is joined. |
| `address` | `text?` | The connection's IP address, as text without a prefix: its IPv4 address, else its global IPv6 address. Null while not connected. Over NetworkManager this is the default-route connection's interface (wired too); over iwd it is the Wi-Fi interface. Read from the kernel, and followed only while a visible reader reads it. |
| `rx` | `float` | Bytes a second received through the machine's network hardware (every interface backed by a device: Ethernet, Wi-Fi, a modem; not loopback, bridges, VPN tunnels or containers' links), from the kernel's counters whichever daemon runs: `graph network.rx { range: auto }`. Sampled once a second while a visible reader reads it or `tx`; while none does but a `graph` keeps history of the service, at the coarser of that and a twentieth of the graph's `history` (at least 2 s); otherwise not at all. 0 until the first second has passed. |
| `tx` | `float` | Bytes a second sent, as `rx` counts them. |
| `scanning` | `bool` | A Wi-Fi scan runs: one `scan()` asked, or the scan a network menu asks when it opens; over iwd, iwd's own scans too. |
| `kind` | `ConnectionKind?` | The kind of the connection carrying the traffic, so a bar picks its icon: `match network.kind { wifi => …, ethernet => …, vpn => …, wireguard => …, _ => … }` (the `_` arm for null and `other`). A VPN or WireGuard tunnel holding the default route counts first, since traffic goes through it; else the connection that holds it (NetworkManager's primary connection). Null while not connected. Over iwd, `wifi` while a network is joined. |
| `connections` | `[Connection]` | The connections saved in NetworkManager, keyed by `id`, by name: a VPN toggle (`for c in network.connections.filter(c => c.kind == vpn) key c.id { … }`), a wired profile, Wi-Fi networks joined before. Read, and followed as they are added, changed or removed, only while a visible reader reads them. NetworkManager's loopback profile is left out. Over iwd, which knows only Wi-Fi networks, it is empty. |

| Method | |
| --- | --- |
| `action disconnect()` | Leaves the Wi-Fi network joined, or stops the one being joined; the daemon then joins nothing on its own until a network is joined again. A join it stops is no failure; if the disconnect itself fails, that join goes on and is reported as any join is. A `disconnect()` while one is in flight (a double click) is dropped. Without a network joined or being joined it fails. A failure is `network.failed`. |
| `action scan()` | Scans for Wi-Fi networks now (a refresh button): `scanning` while it runs, `access_points` read again when it ends. A scan the daemon is already running, or has just run, is not asked again and is no failure. With the radio off, or a Wi-Fi device that cannot scan (its hardware switch off, not ready), it fails, as `network.failed("", error)`. |

| Event | |
| --- | --- |
| `on network.failed(ssid: text, error: text)` | Joining a network failed (no password and no secret agent to ask for one, a wrong one, out of range, timed out, or the service not running): `on network.failed(ssid, error) { … }`. `ssid` is the network the action was about (a connection's `name` for its `up()` and `down()`), "" for one that names none (`scan()`, or a `disconnect()` the service could not take). |
