Skip to content

Add example for wifi_settings_connect library #55

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,4 @@ add_subdirectory(reset)
add_subdirectory(scanvideo)
add_subdirectory(sleep)
add_subdirectory(stdio)
add_subdirectory(wifi_settings_connect)
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,11 @@ even though it is in the Pico SDK
Name|Description
---|---
[stdio_pio](stdio/pio)| Demonstrates adding a custom STDIO driver using a PIO UART

## WiFi

Example using the wifi\_settings\_connect library from pico\_extras.

Name|Description
---|---
[wifi\_settings\_connect\_example](wifi_settings_connect/example)| Demonstrates connecting to WiFi hotspots and sending UDP broadcasts
1 change: 1 addition & 0 deletions wifi_settings_connect/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
add_subdirectory(example)
40 changes: 40 additions & 0 deletions wifi_settings_connect/example/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#
# Copyright (c) 2025 Jack Whitham
#
# SPDX-License-Identifier: BSD-3-Clause
#
# Example for wifi_settings_connect.
#
# This example connects to WiFi using wifi_settings_connect functions,
# and then broadcasts a message on UDP port 1234 every second.
# You can receive these with any tool that can receive
# UDP, e.g. tcpdump, Wireshark, or netcat:
#
# nc -l -u -p 1234
#
# The WiFi connection details must be configured in Flash as described here:
# https://github.com/jwhitham/pico-wifi-settings/blob/master/doc/SETTINGS_FILE.md
#

# only build wifi_settings_connect example if library is available
if (TARGET wifi_settings_connect)
# Build example with async_context tasks running in the background
# You can use pico_cyw43_arch_lwip_poll instead of
# pico_cyw43_arch_lwip_threadsafe_background to use polling, if you prefer.
add_executable(wifi_settings_connect_example
example.c
)
target_include_directories(wifi_settings_connect_example PRIVATE
${CMAKE_CURRENT_LIST_DIR}
)
target_link_libraries(wifi_settings_connect_example
pico_cyw43_arch_lwip_threadsafe_background
wifi_settings_connect
pico_stdlib
)

pico_enable_stdio_usb(wifi_settings_connect_example 1)
pico_enable_stdio_uart(wifi_settings_connect_example 0)

pico_add_extra_outputs(wifi_settings_connect_example)
endif ()
44 changes: 44 additions & 0 deletions wifi_settings_connect/example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# wifi\_settings\_connect example

Example using the wifi\_settings\_connect library to connect to a WiFi hotspot.

The Flash storage location for hotspot details is specified in
`include/wifi_settings/wifi_settings_configuration.h`. It is at
`0x101fc000` (for Pico W) and `0x103fc000` (for Pico 2 W). This
"wifi-settings file" 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
```
To add your WiFi details at this location, please [see the setup instructions in the pico-extras
repo](https://github.com/raspberrypi/pico-extras/tree/master/src/rp2_common/wifi_settings_connect/doc/SETTINGS_FILE.md).

To build this example, first run `cmake` at the top level of the
`pico-playground` repository, specifying the locations for
the `pico-sdk` and `pico-extras` repositories, e.g.:
```
cd /home/user/pico-playground
mkdir build
cd build
cmake -DPICO_SDK_PATH=/home/user/pico-sdk \
-DPICO_EXTRAS_PATH=/home/user/pico-extras \
-DPICO_BOARD=pico_w ..
```
Then, run `make` within the `build/wifi_settings_connect/example`
directory, e.g.
```
cd /home/user/pico-playground
make -C build/wifi_settings_connect/example
```
This will create the UF2 file to be downloaded to the Pico
in `build/wifi_settings_connect/example`.

The example program will search for WiFi hotspots. If it finds a hotspot which
matches those configured in Flash, then it will automatically
connect to it and begin a UDP broadcast. The example program prints
its status to the USB serial port; connect with a terminal program
to see what it is doing.
157 changes: 157 additions & 0 deletions wifi_settings_connect/example/example.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
/**
* Copyright (c) 2025 Jack Whitham
*
* SPDX-License-Identifier: BSD-3-Clause
*
* Example for wifi-settings.
*
* This example connects to WiFi using wifi_settings_connect functions,
* and then broadcasts a message on UDP port 1234 every second.
* You can receive these with any tool that can receive
* UDP, e.g. tcpdump, Wireshark, or netcat:
*
* nc -l -u -p 1234
*
* The WiFi connection details must be configured in Flash as described here:
* https://github.com/jwhitham/pico-wifi-settings/blob/master/doc/SETTINGS_FILE.md
*/


#include <string.h>
#include <time.h>

#include "pico/stdlib.h"
#include "pico/cyw43_arch.h"
#include "pico/bootrom.h"

#include "lwip/pbuf.h"
#include "lwip/tcp.h"

#include "wifi_settings/wifi_settings_connect.h"
#include "wifi_settings/wifi_settings_hostname.h"


bool send_udp_packet(uint count) {
// Send a UDP broadcast to port 1234
char text[256];
bool ok = false;

struct udp_pcb* udp_pcb = udp_new();
if (!udp_pcb) {
printf("Failed to allocate space for UDP PCB!\n");
} else {
snprintf(text, sizeof(text), "Hello World %u from %s\n", count, wifi_settings_get_hostname());
const uint size = strlen(text);
struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM);
if (!p) {
printf("Failed to allocate space for UDP packet!\n");
} else {
memcpy(p->payload, text, size);
ip_addr_t addr;
ipaddr_aton("255.255.255.255", &addr);
const err_t err = udp_sendto(udp_pcb, p, &addr, 1234);
if (err) {
printf("Failed to send UDP packet! error=%d\n", (int) err);
} else {
printf("UDP broadcast, port 1234: %s", text);
ok = true;
}
pbuf_free(p);
}
udp_remove(udp_pcb);
}
return ok;
}

int main() {
stdio_init_all();

// Initialise pico-wifi-settings
int rc = wifi_settings_init();
if (rc != 0) {
panic("wifi_settings_init() failed");
return 1;
}

// Begin connecting to WiFi (this function returns immediately)
wifi_settings_connect();

uint count = 0;
bool stay_in_loop = true;
while (stay_in_loop) {
// clear screen
printf("\x1b[2J\r");

// print host name and board ID
printf("Hostname = %s\n"
"Board ID = %s\n\n",
wifi_settings_get_hostname(),
wifi_settings_get_board_id_hex());
fflush(stdout);

// print connection status
char text[512];
wifi_settings_get_connect_status_text(text, sizeof(text));
printf("%s\n\n", text);
if (wifi_settings_has_no_wifi_details()) {
// Help the user if no SSIDs are configured
printf("You need to configure at least one hotspot! See\n"
"https://github.com/jwhitham/pico-wifi-settings/blob/master/doc/SETTINGS_FILE.md\n"
"for instructions.\n\n");
} else {
wifi_settings_get_hw_status_text(text, sizeof(text));
printf("%s\n", text);
wifi_settings_get_ip_status_text(text, sizeof(text));
printf("%s\n", text);
}
fflush(stdout);

// Send a UDP broadcast to port 1234 if connected
if (wifi_settings_is_connected()) {
if (send_udp_packet(count)) {
count++;
}
}

printf("press 'c' to connect, 'd' to disconnect, 'r' to return to bootloader\n");
fflush(stdout);
switch (getchar_timeout_us(1)) {
case 'c':
wifi_settings_connect();
break;
case 'd':
wifi_settings_disconnect();
break;
case 'r':
stay_in_loop = false;
break;
default:
break;
}
#if PICO_CYW43_ARCH_POLL
// if you are using pico_cyw43_arch_poll, then you must poll periodically from your
// main loop (not from a timer interrupt) to check for wifi_settings, WiFi driver
// or lwIP work that needs to be done.
cyw43_arch_poll();
// you can poll as often as you like, however if you have nothing else to do you can
// choose to sleep:
sleep_ms(1000);
#else
// if you are not using pico_cyw43_arch_poll, then wifi_settings, WiFI driver and lwIP work
// is done via interrupt in the background. This sleep is just an example of some (blocking)
// work you might be doing.
sleep_ms(1000);
#endif
}
printf("That's all\n");

// Disconnection and de-initialisation are optional steps
// with wifi_settings, but you may wish to explicitly stop
// the WiFi connection for some reason:
wifi_settings_disconnect();
wifi_settings_deinit();
printf("Goodbye\n");
// return to boot loader
reset_usb_boot(0, 0);
return 0;
}
85 changes: 85 additions & 0 deletions wifi_settings_connect/example/lwipopts.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#ifndef _LWIPOPTS_H
#define _LWIPOPTS_H


// This example LWIP settings file has been adapted from the pico-examples repo.
// See https://www.nongnu.org/lwip/2_1_x/group__lwip__opts.html for details.
// Note: pico-wifi-settings has been tested with LWIP projects that use NO_SYS and
// don't use LWIP_SOCKET - there has not yet been any attempt to support FreeRTOS.
#define NO_SYS 1
#define LWIP_SOCKET 0
#if PICO_CYW43_ARCH_POLL
#define MEM_LIBC_MALLOC 1
#else
// MEM_LIBC_MALLOC is incompatible with non polling versions
#define MEM_LIBC_MALLOC 0
#endif
#define MEM_ALIGNMENT 4
#define MEM_SIZE 4000
#define MEMP_NUM_TCP_SEG 32
#define MEMP_NUM_ARP_QUEUE 10
#define PBUF_POOL_SIZE 24
#define LWIP_ARP 1
#define LWIP_ETHERNET 1
#define LWIP_ICMP 1
#define LWIP_RAW 1
#define TCP_WND (8 * TCP_MSS)
#define TCP_MSS 1460
#define TCP_SND_BUF (8 * TCP_MSS)
#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1)) / (TCP_MSS))
#define LWIP_NETIF_STATUS_CALLBACK 1
#define LWIP_NETIF_LINK_CALLBACK 1
#define LWIP_NETIF_HOSTNAME 1
#define LWIP_NETCONN 0
#define MEM_STATS 0
#define SYS_STATS 0
#define MEMP_STATS 0
#define LINK_STATS 0
// #define ETH_PAD_SIZE 2
#define LWIP_CHKSUM_ALGORITHM 3
#define LWIP_DHCP 1
#define LWIP_IPV4 1
#define LWIP_TCP 1
#define LWIP_UDP 1
#define LWIP_DNS 1
#define LWIP_TCP_KEEPALIVE 1
#define LWIP_NETIF_TX_SINGLE_PBUF 1
#define DHCP_DOES_ARP_CHECK 0
#define LWIP_DHCP_DOES_ACD_CHECK 0

#ifndef NDEBUG
#define LWIP_DEBUG 1
#define LWIP_STATS 1
#define LWIP_STATS_DISPLAY 1
#endif

#define ETHARP_DEBUG LWIP_DBG_OFF
#define NETIF_DEBUG LWIP_DBG_OFF
#define PBUF_DEBUG LWIP_DBG_OFF
#define API_LIB_DEBUG LWIP_DBG_OFF
#define API_MSG_DEBUG LWIP_DBG_OFF
#define SOCKETS_DEBUG LWIP_DBG_OFF
#define ICMP_DEBUG LWIP_DBG_OFF
#define INET_DEBUG LWIP_DBG_OFF
#define IP_DEBUG LWIP_DBG_OFF
#define IP_REASS_DEBUG LWIP_DBG_OFF
#define RAW_DEBUG LWIP_DBG_OFF
#define MEM_DEBUG LWIP_DBG_OFF
#define MEMP_DEBUG LWIP_DBG_OFF
#define SYS_DEBUG LWIP_DBG_OFF
#define TCP_DEBUG LWIP_DBG_OFF
#define TCP_INPUT_DEBUG LWIP_DBG_OFF
#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF
#define TCP_RTO_DEBUG LWIP_DBG_OFF
#define TCP_CWND_DEBUG LWIP_DBG_OFF
#define TCP_WND_DEBUG LWIP_DBG_OFF
#define TCP_FR_DEBUG LWIP_DBG_OFF
#define TCP_QLEN_DEBUG LWIP_DBG_OFF
#define TCP_RST_DEBUG LWIP_DBG_OFF
#define UDP_DEBUG LWIP_DBG_OFF
#define TCPIP_DEBUG LWIP_DBG_OFF
#define PPP_DEBUG LWIP_DBG_OFF
#define SLIP_DEBUG LWIP_DBG_OFF
#define DHCP_DEBUG LWIP_DBG_OFF

#endif /* __LWIPOPTS_H__ */