Add self-contained documentation for wifi_settings_connect

pull/94/head
Jack Whitham 2025-05-06 23:53:58 +01:00
rodzic 3984658765
commit cdde8e526d
3 zmienionych plików z 312 dodań i 13 usunięć

Wyświetl plik

@ -3,20 +3,39 @@
This is a library to manage WiFi connections. It provides Flash storage
for WiFi passwords and hotspot names, and a background async\_context
service to automatically connect to them. You can store details for
up to 16 hotspots and update them using `picotool` or a setup
up to 100 hotspots and update them using `picotool` or a setup
application. This avoids any need to
specify build-time flags such as `WIFI_SSID` and `WIFI_PASSWORD`.
The Flash storage location for hotspot details is specified in
`include/wifi_settings/wifi_settings_configuration.h`. It is at
`0x101ff000` (for Pico W) and `0x103fe000` (for Pico 2 W). To add your
WiFi details at this location, please [see these
instructions](https://github.com/jwhitham/pico-wifi-settings/blob/master/doc/SETTINGS_FILE.md).
You can edit the settings as a text file and transfer it with `picotool`,
or install a [setup application](https://github.com/jwhitham/pico-wifi-settings/blob/master/doc/SETUP_APP.md)
to add or update WiFi details.
WiFi hotspot details are stored in a Flash sector that isn't normally used by programs,
normally located near the end of Flash memory. This
[wifi-settings file](doc/SETTINGS_FILE.md) is a simple text file which
can be updated by USB or by installing a setup app from the
[pico-wifi-settings home page](https://github.com/jwhitham/pico-wifi-settings)
on Github.
This wifi\_settings\_connect library is a subset of a larger
library, [wifi\_settings](https://github.com/jwhitham/pico-wifi-settings/),
which adds remote update functions for both the WiFi settings
and (optionally) your Pico application too.
## Requirements
- Raspberry Pi Pico W or Pico 2 W hardware
- a "bare metal" C/C++ application for Pico W (not FreeRTOS)
using the `cyw43` driver and `lwip` network stack
which are provided with the [Pico SDK](https://github.com/raspberrypi/pico-sdk/).
- between 2kb and 13kb of code space depending on options used
- WiFi network(s) with a DHCP server and WPA authentication
## How to use it
First, you need to configure the WiFi settings file
in Flash. See the [wifi-settings file documentation](doc/SETTINGS_FILE.md).
Next, you need to modify your application to use wifi\_settings\_connect.
There is an [integration guide which explains what you need to do
to add wifi\_settings\_connect to your application](doc/INTEGRATION.md).
## Enabling remote updates
wifi\_settings\_connect is a subset of a larger library (wifi\_settings) which
also has support for remote updates of WiFi settings and over-the-air (OTA)
firmware updates. Visit the
[pico-wifi-settings home page](https://github.com/jwhitham/pico-wifi-settings)
for more information.

Wyświetl plik

@ -0,0 +1,120 @@
# Integrating wifi\_settings\_connect into your own Pico application
You can integrate wifi\_settings\_connect into your own Pico application
with just a few lines of code:
```
#include "wifi_settings.h" // << add this
int main() {
stdio_init_all();
if (wifi_settings_init() != 0) { // << and add this
panic(...);
}
wifi_settings_connect(); // << and add this
// and that's it...
}
```
The following steps go through the process in more detail for
a [CMake](https://cmake.org) project stored in Git,
similar to all of the official Pico projects.
You may find it useful to look at [the example app for wifi\_settings\_connect in
the pico-playground repository](https://github.com/raspberrypi/pico-playground/tree/master/wifi_settings_connect/example).
## Modify CMakeLists.txt to use the library
The `target_link_libraries` rule for your project should be extended to
add `wifi_settings_connect`.
```
target_link_libraries(your_app
wifi_settings_connect
pico_stdlib
)
```
If your project does not include the `pico-extras` repository, then this
must also be added.
```
include(pico_extras_import.cmake)
```
You can copy the `pico_extras_import.cmake` file from [the root of
the pico-playground repository](https://github.com/raspberrypi/pico-playground).
### Additional configuration for LwIP and mbedtls
If your project has not previously used WiFi you will also need
to add one of the WiFi driver targets to `target_link_libraries`, e.g.
`pico_cyw43_arch_lwip_background` or `pico_cyw43_arch_lwip_poll`.
You will also need `lwipopts.h` in the project directory (this configures
LwIP). You can copy an example from
[here](https://github.com/raspberrypi/pico-playground/tree/master/wifi_settings_connect/example).
## Include the header file
Your main C/C++ source file (containing `main()`) should be modified to include
`wifi_settings/wifi_settings_connect.h`:
```
#include "wifi_settings/wifi_settings_connect.h"
```
## Modify your main function
Your `main()` function should be modified to call `wifi_settings_init()` once on startup.
- This must *replace* any call to `cyw43` initialisation functions, because
these are called from `wifi_settings_init()` (with the correct country code).
- The call should be after `stdio_init_all()`.
- If the call returns a non-zero value, an error has occurred. You do not have
to handle this error; it is still safe to call other `wifi_settings` functions,
but they will not work and will return error codes where appropriate.
Your application should also call `wifi_settings_connect()` when it wishes to connect
to WiFi. This can be called immediately after `wifi_settings_init()` or at any later
time. `wifi_settings_connect()` does not block, as the connection takes
place in the background.
All other modifications are optional. You can now rebuild your application
and it will include the wifi\_settings\_connect features.
## CMake command line
When running `cmake`, you need to provide the location of the `pico-extras`
repository as well as the `pico-sdk` repository. This is typically done
with `-DPICO_EXTRAS_PATH`, e.g.:
```
cmake -DPICO_BOARD=pico_w \
-DPICO_SDK_PATH=/home/user/pico-sdk \
-DPICO_EXTRAS_PATH=/home/user/pico-extras \
..
```
# Optional modifications
Your application can call `wifi_settings_is_connected()` at any time
to determine if the WiFi connection is available or not.
Your application can call various status functions at any time
to get a text report on the connection status. This can be useful for debugging.
Each function should be passed a `char[]` buffer for the output, along with the
size of the buffer.
- `wifi_settings_get_connect_status_text()` produces a line of
text showing the connection status, e.g. `WiFi is connected to ssid1=MyHomeWiFi`.
- `wifi_settings_get_hw_status_text()` produces a line of
text describing the status of the `cyw43` hardware driver; this will be empty
if the hardware is not initialised.
- `wifi_settings_get_ip_status_text()` produces a line of
text describing the status of the `lwip` network stack e.g. IP address; this will be empty
if unconnected.
There is also a function to report the current connection state
`wifi_settings_get_ssid_status()` returns
a pointer to a static string, indicating the status of a connection attempt to
an SSID, e.g. `SUCCESS`, `NOT FOUND`.
Your application can call `wifi_settings_disconnect()` to force disconnect,
or `wifi_settings_deinit()` to deinitialise the driver, but this is never necessary
and these steps can be left out. They exist to allow the application to shut down WiFi,
e.g. to save power, or in order to control the WiFi hardware directly for some other
purpose. For example, the
[setup app](https://github.com/jwhitham/pico-wifi-settings/tree/master/doc/SETUP_APP.md)
uses this feature to perform its own WiFi scan.

Wyświetl plik

@ -0,0 +1,160 @@
# Creating and updating a WiFi settings file
wifi\_settings\_connect stores WiFi hotspot names and passwords
in a Flash sector that isn't normally used by programs. This
is called the "WiFi settings file". It is similar to a file on a disk,
except that it is always at the same location, and the size is
limited to 4096 bytes.
The file can be updated over USB by using [picotool](https://github.com/raspberrypi/picotool).
It is a text file which can be edited with any text editor.
Here is an example of typical contents:
```
ssid1=MyHomeWiFi
pass1=mypassword1234
ssid2=MyPhoneHotspot
pass2=secretpassword
country=GB
```
wifi\_settings\_connect will automatically scan for hotspots and connect to
hotspots matching the SSID names and passwords in the file.
- On the [pico-wifi-settings home page](https://github.com/jwhitham/pico-wifi-settings)
you can also find a setup app which runs on your Pico and automates much of the
setup process. The pico-wifi-settings library is a superset of
wifi\_settings\_connect. It includes a remote update feature that allows
a new wifi-settings file to be installed via WiFi.
# Creating the file on a computer
Use any text editor to create a text file similar to the example above.
Each line in the file should contain a key and a value, separated by `=`,
with no spaces around `=`, or at the beginning or end of each line.
The file must have at least `ssid1` or `bssid1`, otherwise there will
be no connection attempts, and wifi\_settings\_connect will stay in the
STORAGE\_EMPTY\_ERROR state.
You can also use the following:
- `ssid<N>` - SSID name for hotspot N (a number from 1 to 100)
- `pass<N>` - Password for hotspot N
- `country` - Your two-letter country code from [ISO-3166-1](https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes)
- `bssid<N>` - The BSSID ID for hotspot N
- `name` - The hostname of the Pico (sent to DHCP servers)
# Copying the WiFi settings file by USB
You can use [picotool](https://github.com/raspberrypi/picotool) to copy the
file from your PC to your Pico via USB.
picotool is part of the Pico SDK.
You need to build picotool with USB support for your OS (or download a pre-built copy).
To use picotool,
boot the Pico in bootloader mode by holding down the BOOTSEL button while plugging it
into USB. In bootloader mode, you can upload files with picotool.
The default address is 16kb before the final address in Flash:
- On Pico W, use `0x101fc000` as the address.
- On Pico 2 W, use `0x103fc000` as the address.
You must also rename your WiFi settings file so that it ends with `.bin` as
picotool is not able to upload files unless they are `.bin`, `.elf` or `.uf2`.
Here is a sample upload command for Pico W (RP2040):
```
picotool load -o 0x101fc000 mywifisettings.bin
```
and the equivalent for Pico 2 W (RP2350):
```
picotool load -o 0x103fc000 mywifisettings.bin
```
## Location of the wifi-settings file
The default location of the file (16kb before the final address in Flash)
has been chosen because the final three 4kb Flash sectors are already assigned
a function by the Pico SDK. The Bluetooth library uses two 4kb sectors for storage of
devices that have been paired by Bluetooth. The final 4kb sector is used for a workaround
for the RP2350-E10 bug - this sector may be erased when copying a UF2 file to a Pico 2
via drag-and-drop. Therefore, these three sectors are avoided.
If you wish to store the wifi-settings file at a specific address you can
do so by setting `-DWIFI_SETTINGS_FILE_ADDRESS=0x....` when running `cmake`.
The value `0x...` should be an address relative to the start of Flash, so Flash address
`0x1fc000` corresponds to absolute address `0x101fc000`.
## Backing up a WiFi settings file
picotool can be used to download WiFi settings files from a Pico W:
```
picotool save -r 0x101fc000 0x101fd000 backup.bin
```
and Pico 2 W (RP2350):
```
picotool save -r 0x103fc000 0x103fd000 backup.bin
```
Characters after the end of the file will be copied (usually either 0x00 or 0xff).
These can be safely deleted using your text editor. The backup is restored by
using `picotool load` as described in "Copying the WiFi settings file by USB".
These examples use the default location for the wifi-settings file. If you
are using a custom location, e.g. building with
`-DWIFI_SETTINGS_FILE_ADDRESS=0x...`, then
you would need to substitute the actual address.
# File format details
The file format is very simple so that it can be read by a simple algorithm
that doesn't require much code space. The parser ignores any line that it
doesn't understand, and skips any keys that are not known. Here are the rules:
- The key and the value should be separated only by an `=` character, e.g. `ssid1=HomeWiFi`.
- Lines that don't match the form `key=value` are completely ignored;
you can add text, comments etc. in order to help you manage your configuration.
- On a line that does match `key=value`, whitespace is NOT ignored.
Be careful to avoid adding extra spaces around `=`.
A space before `=` will be part of the key, and a space after `=` will be part of the value.
- Unix and Windows line endings are supported.
- The maximum size of the file is 4096 bytes.
- Values can contain any printable UTF-8 character.
- Keys can also contain any printable UTF-8 character except for '='.
- There is no maximum size for a key or a value (except for the file size).
- Values can be zero length.
- Keys must be at least 1 byte.
- If a key appears more than once in the file, the first value is used.
- The end of the file is the first byte with value 0x00, 0xff or 0x1a, or the 4097th byte,
whichever comes first.
# WiFi settings
- `ssid<N+1>` is only checked if `ssid<N>` is present.
- The number reflects the priority. Lower numbers take priority over higher
numbers when more than one SSID is found.
- If `pass<N>` is not specified then wifi\_settings\_connect will assume
an open WiFi hotspot.
- If both `bssid<N>` and `ssid<N>` are specified, then the BSSID is used
and the SSID is ignored.
- If you don't specify a country, the default worldwide settings are used, which might work
slightly less well (e.g. fewer WiFi channels are supported).
- `bssid<N>` should be specified as
a `:`-separated lower-case MAC address, e.g. `01:23:45:67:89:ab`. BSSIDs are
not normally required and should only be used if you have a special requirement
e.g. a "hidden" hotspot without an SSID name.
# Custom keys and values
The WiFi settings file can have keys which are not used by the wifi\_settings\_connect library.
Your application can obtain their values using the `wifi_settings_get_value_for_key()` function.
This can be a useful way to store additional configuration data for your Pico application.
For example you might use it to store encryption keys, server addresses, user names
or any other setting that you may wish to update without rebuilding your application.
`wifi_settings_get_value_for_key` uses a linear search, starting at the beginning
of the file. This search does not backtrack and is fast because of the simplistic
nature of the file format. However, in algorithmic terms, this is not the best way
to implement or search a key/value store, and if you need frequent access to keys/values,
you may wish to implement something better (e.g. use a hash table to implement a dictionary)
or just load the values when your application starts up and then store them elsewhere.