# `VintageNetWiFi`
[🔗](https://github.com/nerves-networking/vintage_net_wifi/blob/v0.12.9/lib/vintage_net_wifi.ex#L13)

WiFi support for VintageNet

Configurations for this technology are maps with a `:type` field set to
`VintageNetWiFi`. The following additional fields are supported:

* `:vintage_net_wifi` - WiFi options
* `:ipv4` - IPv4 options. See VintageNet.IP.IPv4Config.

To scan for WiFi networks it's sufficient to use an empty configuration and call
the `VintageNet.scan("wlan0")`:

```elixir
%{type: VintageNetWiFi}
```

Here's a typical configuration for connecting to a WPA2-protected Wi-Fi network:

```elixir
%{
  type: VintageNetWiFi,
  vintage_net_wifi: %{
    mode: :infrastructure,
    networks: [%{ssid: "my_network_ssid", key_mgmt: :wpa_psk, psk: "a_passphrase_or_psk"}]
  },
  ipv4: %{method: :dhcp}
}
```

If your Wi-Fi adapter or module has support for running as an Access Point,
then the following configuration puts it in AP mode, assigns a static IP
address of 192.168.0.1 and gives clients IP addresses from 192.168.0.30
to 192.168.0.254.

```elixir
%{
  type: VintageNetWiFi,
  vintage_net_wifi: %{
    mode: :ap,
    networks: [
      %{
        ssid: "test ssid",
        key_mgmt: :none
      }
    ]
  },
  ipv4: %{
    method: :static,
    address: {192, 168, 0, 1},
    prefix_length: 24
  },
  dhcpd: %{
    start: {192, 168, 0, 30},
    end: {192, 168, 0, 254}
  }
}
```

To enable verbose log messages from the `wpa_supplicant`, add `verbose: true` to the
configuration.

# `qr_options`

```elixir
@type qr_options() :: [hidden: boolean(), type: :WPA | :WEP | :nopass]
```

# `capabilities`

```elixir
@spec capabilities(VintageNet.ifname()) :: map()
```

Experimental API for getting WiFi driver capabilities

This queries the `wpa_supplicant` and driver to see what it supports. It's
useful for seeing whether WPA3, 5 GHz, and other things are supported. The
results aren't currently processed.

# `network_configured?`

```elixir
@spec network_configured?(map()) :: boolean()
```

Helper for checking whether a WiFi configuration has a network configured

This is useful for checking whether a WiFi configuration is just good for
scanning for WiFi networks or whether it actually could connect to another
computer.

Returns `false` if the configuration isn't a VintageNetWiFi one or if no
networks were specified.

To test if an `ifname` has a network configured, run:

```
VintageNet.get_configuration(ifname) |> network_configured?()
```

# `qr_string`

```elixir
@spec qr_string(String.t(), String.t(), qr_options()) :: String.t()
```

Create a WiFi network config string for use in a QR Code

A QR Code created from the string returned by this function is scannable by
almost any smartphone to allow easy access to a Wi-Fi network. The user only
needs to agree to a prompt rather than enter credentials manually.

See https://github.com/zxing/zxing/wiki/Barcode-Contents#wi-fi-network-config-android-ios-11
for more format details.

# `quick_configure`

```elixir
@spec quick_configure(String.t(), String.t() | nil) :: :ok | {:error, term()}
```

Configure WiFi using the most common settings

If your network requires a password (WPA2 PSK and WPA3 SAE networks):

```
iex> VintageNetWiFi.quick_configure("ssid", "password")
:ok
```

If you're connecting to an open network, don't pass the password. Keep in
mind that if you're at a cafe or other location that has a captive portal,
`VintageNetWiFi` isn't smart enough to bypass it.

```
iex> VintageNetWiFi.quick_configure("open_wifi_ssid")
:ok
```

Then run `VintageNet.info` to see when the network connects. If you're
writing a program, run `VintageNet.get(["interface", "wlan0", "connection"])`
to get the connection status or subscribe to that property for change
notifications.

If you're on an enterprise network or use static IP addresses or need any
other special configuration handling, you'll need to call
`VintageNet.configure/3` instead. See `VintageNetWiFi.Cookbook` for help with
creating configurations or manually construct the configuration map.

> #### WiFi Authentication {: .info}
>
> VintageNetWiFi doesn't know whether the WiFi hardware you're using fully
> supports WPA3 authentication. To avoid hard to understand errors,
> `quick_configure/2` defaults to WPA2. If you have hardware that supports
> WPA3 and would like to use WPA2/WPA3 generic configurations, update your
> `config.exs` to:
>
> ```
> config :vintage_net_wifi, :quick_configure, &VintageNetWiFi.Cookbook.generic/2
> ```

# `quick_scan`

```elixir
@spec quick_scan(non_neg_integer()) :: [VintageNetWiFi.AccessPoint.t()]
```

Convenience function to scan for access points

This function initiates a scan, waits, and then returns all of the discovered
access points. It's intended for quickly seeing what's around.

If you'd like to use this in a program, but want to display access point options
as they're found, here's how to do it:

```elixir
VintageNet.subscribe(["interface", "wlan0", "wifi", "access_points"])
VintageNet.scan("wlan0")
```

Then wait for messages. They'll be of the form:

```elixir
{VintageNet, ["interface", "wlan0", "wifi", "access_points"], old_value, new_value, meta}
```

Both `old_value` and `new_value` will be lists of access points. You'll need
call `VintageNet.scan/1` every 30 seconds or so to repeat the scan across all
WiFi channels. See also `VintageNetWiFi.summarize_access_points/1` to get an
easier to manage list of access points for presentation to users.

# `quick_wps`

```elixir
@spec quick_wps(non_neg_integer()) :: {:ok, map()} | {:error, String.t()}
```

Quick way to receive WiFi credentials via WPS PBC

Call this function with a long enough timeout for you to press the WPS button
on your access point.  The WiFi gets configured as soon as the WPS
credentials are received.

```elixir
VintageNetWiFi.quick_wps(60_000)
# Press WPS button on AP
:ok
```

# `summarize_access_points`

```elixir
@spec summarize_access_points([VintageNetWiFi.AccessPoint.t()]) :: [
  VintageNetWiFi.AccessPoint.t()
]
```

Summarize access point lists

This function summarizes a list of access points, such as those returned from
`quick_scan/1` or via calls to `VintageNet.scan/1` checking the
`["interface", "wlan0", "wifi", "access_points"]` property.  The summary
provides a list that most people are used to seeing when looking for access
points. It does the following:

* When the same SSID is found on multiple channels, it picks the one with the
  best signal and removes the others.
* Filter out SSIDs used by mesh routers and other devices that wouldn't work
* Sort SSIDs by signal strength

---

*Consult [api-reference.md](api-reference.md) for complete listing*
