From b0acb56ed36eb4aff5d64a5a82a32b3d294b026e Mon Sep 17 00:00:00 2001 From: Ismail Mehmood Date: Sat, 28 Jun 2025 13:03:24 +0100 Subject: [PATCH 1/7] feat(created structure for UDP server) --- README.md | 1 + pico_w/wifi/python_test_udp/python_test_udp_client.py | 1 + pico_w/wifi/udp_server/CMakeLists.txt | 1 + pico_w/wifi/udp_server/lwipopts.h | 1 + pico_w/wifi/udp_server/picow_udp_server.c | 1 + 5 files changed, 5 insertions(+) create mode 100644 pico_w/wifi/python_test_udp/python_test_udp_client.py create mode 100644 pico_w/wifi/udp_server/CMakeLists.txt create mode 100644 pico_w/wifi/udp_server/lwipopts.h create mode 100644 pico_w/wifi/udp_server/picow_udp_server.c diff --git a/README.md b/README.md index 5a436a348..467f2aa85 100644 --- a/README.md +++ b/README.md @@ -188,6 +188,7 @@ App|Description [picow_ntp_client](pico_w/wifi/ntp_client) | Connects to an NTP server to fetch and display the current time. [picow_tcp_client](pico_w/wifi/tcp_client) | A simple TCP client. You can run [python_test_tcp_server.py](pico_w/wifi/python_test_tcp/python_test_tcp_server.py) for it to connect to. [picow_tcp_server](pico_w/wifi/tcp_server) | A simple TCP server. You can use [python_test_tcp_client.py](pico_w//wifi/python_test_tcp/python_test_tcp_client.py) to connect to it. +[picow_udp_server](pico_w/wifi/udp_server) | A simple UDP server. You can use [python_test_udp_client.py](pico_w//wifi/python_test_udp/python_test_udp_client.py) to connect to it. [picow_tls_client](pico_w/wifi/tls_client) | Demonstrates how to make a HTTPS request using TLS. [picow_tls_verify](pico_w/wifi/tls_client) | Demonstrates how to make a HTTPS request using TLS with certificate verification. [picow_wifi_scan](pico_w/wifi/wifi_scan) | Scans for WiFi networks and prints the results. diff --git a/pico_w/wifi/python_test_udp/python_test_udp_client.py b/pico_w/wifi/python_test_udp/python_test_udp_client.py new file mode 100644 index 000000000..3cf48f71b --- /dev/null +++ b/pico_w/wifi/python_test_udp/python_test_udp_client.py @@ -0,0 +1 @@ +# TO DO: Implement UDP client tester for Pico \ No newline at end of file diff --git a/pico_w/wifi/udp_server/CMakeLists.txt b/pico_w/wifi/udp_server/CMakeLists.txt new file mode 100644 index 000000000..705e1ae2e --- /dev/null +++ b/pico_w/wifi/udp_server/CMakeLists.txt @@ -0,0 +1 @@ +# CMake File for UDP Server \ No newline at end of file diff --git a/pico_w/wifi/udp_server/lwipopts.h b/pico_w/wifi/udp_server/lwipopts.h new file mode 100644 index 000000000..bdc20d2e8 --- /dev/null +++ b/pico_w/wifi/udp_server/lwipopts.h @@ -0,0 +1 @@ +// TO DO: Create LWIP options \ No newline at end of file diff --git a/pico_w/wifi/udp_server/picow_udp_server.c b/pico_w/wifi/udp_server/picow_udp_server.c new file mode 100644 index 000000000..d9b3df138 --- /dev/null +++ b/pico_w/wifi/udp_server/picow_udp_server.c @@ -0,0 +1 @@ +// TO DO: Implement UDP Server for Pico \ No newline at end of file From c17100583110fad3372562d8b6dc3a38940ad6f8 Mon Sep 17 00:00:00 2001 From: Ismail Mehmood Date: Sat, 28 Jun 2025 13:13:01 +0100 Subject: [PATCH 2/7] feat(added python testing for UDP server) --- .../python_test_udp/python_test_udp_client.py | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/pico_w/wifi/python_test_udp/python_test_udp_client.py b/pico_w/wifi/python_test_udp/python_test_udp_client.py index 3cf48f71b..d8e4602af 100644 --- a/pico_w/wifi/python_test_udp/python_test_udp_client.py +++ b/pico_w/wifi/python_test_udp/python_test_udp_client.py @@ -1 +1,31 @@ -# TO DO: Implement UDP client tester for Pico \ No newline at end of file +import socket +import time + +# === Configuration === +PICO_IP = "PI_IP_HERE" # Replace with your Pico's IP +PICO_PORT = 12345 # Port Pico is listening on + +# === Data to send === +data = { + "1.": "Message 1 received!", + "2.": "Message 2 received!", + "3.": "Message 3 received!", + "4.": "Message 4 received!", + "5.": "Message 5 received!" +} + +# === Create UDP socket === +sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + +try: + for key, value in data.items(): + message = f"{key}:{value}" + print(f"Sending to {PICO_IP}:{PICO_PORT} -> {message}") + sock.sendto(message.encode(), (PICO_IP, PICO_PORT)) + time.sleep(0.1) # slight delay to prevent message loss + +except Exception as e: + print(f"Error: {e}") + +finally: + sock.close() From 8d347e50689b91d943babd6b3d2de8c2a27565c5 Mon Sep 17 00:00:00 2001 From: Ismail Mehmood Date: Sat, 28 Jun 2025 13:20:05 +0100 Subject: [PATCH 3/7] feat(populated lwipopts.h with example header) --- pico_w/wifi/udp_server/lwipopts.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/pico_w/wifi/udp_server/lwipopts.h b/pico_w/wifi/udp_server/lwipopts.h index bdc20d2e8..8571ed509 100644 --- a/pico_w/wifi/udp_server/lwipopts.h +++ b/pico_w/wifi/udp_server/lwipopts.h @@ -1 +1,10 @@ -// TO DO: Create LWIP options \ No newline at end of file +#ifndef _LWIPOPTS_H +#define _LWIPOPTS_H + +// Generally you would define your own explicit list of lwIP options +// (see https://www.nongnu.org/lwip/2_1_x/group__lwip__opts.html) +// +// This example uses a common include to avoid repetition +#include "lwipopts_examples_common.h" + +#endif From 5f3494fd1a9d6f226d9cb70a0c46700cff57e690 Mon Sep 17 00:00:00 2001 From: Ismail Mehmood Date: Sat, 28 Jun 2025 13:35:32 +0100 Subject: [PATCH 4/7] feat(added wifi handling and UDP server functions) --- pico_w/wifi/udp_server/CMakeLists.txt | 42 ++- pico_w/wifi/udp_server/picow_udp_server.c | 410 +++++++++++++++++++++- 2 files changed, 450 insertions(+), 2 deletions(-) diff --git a/pico_w/wifi/udp_server/CMakeLists.txt b/pico_w/wifi/udp_server/CMakeLists.txt index 705e1ae2e..4ed1b06a5 100644 --- a/pico_w/wifi/udp_server/CMakeLists.txt +++ b/pico_w/wifi/udp_server/CMakeLists.txt @@ -1 +1,41 @@ -# CMake File for UDP Server \ No newline at end of file +# Threadsafe + +add_executable(picow_udp_server_background + picow_udp_server.c + ) +target_compile_definitions(picow_udp_server_background PRIVATE + WIFI_SSID=\"${WIFI_SSID}\" + WIFI_PASSWORD=\"${WIFI_PASSWORD}\" + ) +target_include_directories(picow_udp_server_background PRIVATE + ${CMAKE_CURRENT_LIST_DIR} + ${CMAKE_CURRENT_LIST_DIR}/.. # for the common lwipopts.h + ) +target_link_libraries(picow_udp_server_background + pico_cyw43_arch_lwip_threadsafe_background + pico_stdlib + ) + +pico_add_extra_outputs(picow_udp_server_background) + +# Manual polling + +add_executable(picow_udp_server_poll + picow_tcp_server.c + ) +target_compile_definitions(picow_udp_server_poll PRIVATE + WIFI_SSID=\"${WIFI_SSID}\" + WIFI_PASSWORD=\"${WIFI_PASSWORD}\" + ) +target_include_directories(picow_udp_server_poll PRIVATE + ${CMAKE_CURRENT_LIST_DIR} + ${CMAKE_CURRENT_LIST_DIR}/.. # for our common lwipopts + ) +target_link_libraries(picow_udp_server_poll + pico_cyw43_arch_lwip_poll + pico_stdlib + ) +pico_add_extra_outputs(picow_udp_server_poll) + +pico_enable_stdio_usb(picow_udp_server_poll 1) +pico_enable_stdio_usb(picow_udp_server_background 1) diff --git a/pico_w/wifi/udp_server/picow_udp_server.c b/pico_w/wifi/udp_server/picow_udp_server.c index d9b3df138..dc6cd5598 100644 --- a/pico_w/wifi/udp_server/picow_udp_server.c +++ b/pico_w/wifi/udp_server/picow_udp_server.c @@ -1 +1,409 @@ -// TO DO: Implement UDP Server for Pico \ No newline at end of file +#include "pico/stdlib.h" +#include "pico/cyw43_arch.h" +#include "lwip/pbuf.h" +#include "lwip/tcp.h" +#include "lwip/dns.h" +#include "lwip/netif.h" +#include "lwip/udp.h" +#include "lwip/ip_addr.h" +#include "lwip/dhcp.h" +#include "lwip/ip4_addr.h" +#include +#include +#include + +// Connection timeout in ms +#define WIFI_CONNECT_TIMEOUT_MS 30000 + +static bool wifi_connected = false; +static absolute_time_t connection_start_time; + +// Default UDP port +#ifndef UDP_PORT +#define UDP_PORT 12345 +#endif + +// Maximum message size +#define MAX_UDP_MSG_SIZE 1024 + +// Initialize WiFi hardware +int wifi_init(void) { + // Initialize the CYW43 driver + if (cyw43_arch_init()) { + printf("Failed to initialize CYW43 driver\n"); + return -1; + } + + // Enable station mode + cyw43_arch_enable_sta_mode(); + + printf("WiFi initialized successfully\n"); + return 0; +} + +#define WIFI_CONNECT_TIMEOUT_MS 30000 + +int wifi_connect(const char *ssid, const char *password) { + if (!ssid || !password) { + ssid = WIFI_SSID; + password = WIFI_PASSWORD; + } + + printf("Connecting to WiFi network: %s\n", ssid); + + cyw43_wifi_pm(&cyw43_state, CYW43_PERFORMANCE_PM); + + int ssid_len = strlen(ssid); + + if (cyw43_arch_wifi_connect_timeout_ms(WIFI_SSID, WIFI_PASSWORD, + CYW43_AUTH_WPA2_AES_PSK, WIFI_CONNECT_TIMEOUT_MS)) { + printf("failed to connect.\n"); + return 1; + } else { + printf("Connected.\n"); + wifi_connected = true; + wifi_update_led(); + } + + printf("WiFi link is up, starting client...\n"); + + + printf("DHCP assigned IP: %s\n", ip4addr_ntoa( + netif_ip4_addr(netif_default))); + printf("Netmask: %s\n", ip4addr_ntoa(netif_ip4_netmask(netif_default))); + printf("Gateway: %s\n", ip4addr_ntoa(netif_ip4_gw(netif_default))); + + return 0; +} + +// Disconnect from WiFi +void wifi_disconnect(void) { + if (wifi_connected) { + cyw43_arch_wifi_connect_async("", "", CYW43_AUTH_OPEN); + wifi_connected = false; + wifi_update_led(); + printf("WiFi disconnected\n"); + } +} + +// Check WiFi connection status +bool wifi_is_connected(void) { + // Check hardware link status + int link_status = cyw43_wifi_link_status(&cyw43_state, CYW43_ITF_STA); + + if (link_status == CYW43_LINK_UP) { + wifi_connected = true; + wifi_update_led(); + return true; + } else { + wifi_connected = false; + wifi_update_led(); + return false; + } +} + +// Get WiFi connection status string +const char* wifi_get_status_string(void) { + int link_status = cyw43_wifi_link_status(&cyw43_state, CYW43_ITF_STA); + + switch (link_status) { + case CYW43_LINK_DOWN: + return "Link Down"; + case CYW43_LINK_JOIN: + return "Joining"; + case CYW43_LINK_NOIP: + return "Connected (No IP)"; + case CYW43_LINK_UP: + return "Connected"; + case CYW43_LINK_FAIL: + return "Connection Failed"; + case CYW43_LINK_NONET: + return "No Network"; + case CYW43_LINK_BADAUTH: + return "Bad Authentication"; + default: + return "Unknown"; + } +} + +// Get IP address as string +const char* wifi_get_ip_address(void) { + if (wifi_connected) { + return ip4addr_ntoa(netif_ip4_addr(netif_default)); + } + printf("Not connected."); + return "0.0.0.0"; +} + +// Attempt to reconnect if connection is lost +int wifi_check_and_reconnect(void) { + if (!wifi_is_connected()) { + printf("WiFi connection lost, attempting to reconnect...\n"); + return wifi_connect(NULL, NULL); + } + wifi_update_led(); + return 0; +} + +// Clean up WiFi resources +void wifi_deinit(void) { + wifi_disconnect(); + wifi_update_led(); + cyw43_arch_deinit(); + printf("WiFi deinitialized\n"); +} + +// Set WiFi LED based on connection status +void wifi_update_led(void) { + cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, wifi_connected ? 1 : 0); +} + +// Periodic WiFi maintenance (call from main loop) +void wifi_poll(void) { + // Update LED status + wifi_update_led(); + + // Check connection periodically + static absolute_time_t last_check = 0; + absolute_time_t now = get_absolute_time(); + + if (absolute_time_diff_us(last_check, now) > 5000000) { + // Check every 5 seconds + wifi_check_and_reconnect(); + last_check = now; + } + + // Poll CYW43 driver + cyw43_arch_poll(); +} + +// UDP control block +static struct udp_pcb *udp_pcb = NULL; +static uint16_t listen_port = UDP_PORT; +static udp_data_callback_t data_callback = NULL; +static bool udp_server_active = false; + +// Buffer for incoming data +static uint8_t rx_buffer[MAX_UDP_MSG_SIZE]; + +// Callback function for receiving UDP data +static void udp_recv_callback(void *arg, struct udp_pcb *pcb, struct pbuf *p, + const ip_addr_t *addr, u16_t port) { + if (p != NULL) { + // Copy data to buffer + size_t data_len = p->tot_len; + if (data_len > MAX_UDP_MSG_SIZE) { + data_len = MAX_UDP_MSG_SIZE; + } + + // Copy pbuf data to our buffer + pbuf_copy_partial(p, rx_buffer, data_len, 0); + + printf("UDP received %d bytes from %s:%d\n", data_len, + ip4addr_ntoa(addr), port); + + // Call user callback if registered + if (data_callback) { + data_callback(rx_buffer, data_len, addr, port); + } + + // Free the pbuf + pbuf_free(p); + } +} + +// Initialize UDP handler +int udp_server_init(udp_data_callback_t callback) { + printf("Initializing UDP handler...\n"); + + if (!callback) { + printf("Error: NULL callback passed to udp_server_init\n"); + return -1; + } + + data_callback = callback; // Save the app-level callback + return udp_server_start(UDP_PORT, callback); // Start server via saved port +} + + +// Start UDP server on specified port +int udp_server_start(uint16_t port, udp_data_callback_t callback) { + if (udp_server_active) { + printf("UDP server already active\n"); + return -1; + } + + // if (!wifi_is_connected()) { + // printf("WiFi not connected, cannot start UDP server\n"); + // return -1; + // } + + // Create PCB + udp_pcb = udp_new(); + if (!udp_pcb) { + printf("Failed to create UDP PCB\n"); + return -1; + } + + if (udp_bind(udp_pcb, IP_ADDR_ANY, port) != ERR_OK) { + printf("Failed to bind UDP port %d\n", port); + udp_remove(udp_pcb); + udp_pcb = NULL; + return -1; + } + + // Register internal receive callback + udp_recv(udp_pcb, udp_recv_callback, NULL); + + listen_port = port; + udp_server_active = true; + + printf("UDP server started on port %d\n", port); + return 0; +} + + +// Stop UDP server +void udp_server_stop(void) { + if (udp_pcb) { + udp_remove(udp_pcb); + udp_pcb = NULL; + } + + udp_server_active = false; + data_callback = NULL; + printf("UDP server stopped\n"); +} + +// Send UDP data to specified address and port +int udp_send_data(const ip_addr_t *dest_addr, uint16_t dest_port, + const uint8_t *data, size_t data_len) { + + if (data_len > MAX_UDP_MSG_SIZE) { + printf("Data too large for UDP packet\n"); + return -1; + } + + // Create a temporary PCB for sending if no server running + struct udp_pcb *send_pcb = udp_pcb; + bool temp_pcb = false; + + if (!send_pcb) { + send_pcb = udp_new(); + if (!send_pcb) { + printf("Failed to create UDP PCB for sending\n"); + return -1; + } + temp_pcb = true; + } + + // Allocate pbuf for data + struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, data_len, PBUF_RAM); + if (!p) { + printf("Failed to allocate pbuf\n"); + if (temp_pcb) { + udp_remove(send_pcb); + } + return -1; + } + + // Copy data to pbuf + memcpy(p->payload, data, data_len); + + // Send the data + err_t err = udp_sendto(send_pcb, p, dest_addr, dest_port); + + // Free pbuf + pbuf_free(p); + + // Clean up temporary PCB + if (temp_pcb) { + udp_remove(send_pcb); + } + + if (err != ERR_OK) { + printf("Failed to send UDP data, error: %d\n", err); + return -1; + } + + printf("UDP sent %d bytes to %s:%d\n", data_len, ip4addr_ntoa(dest_addr), + dest_port); + return 0; +} + +// Send UDP data to IP address string +int udp_send_to_ip_string(const char *ip_str, uint16_t dest_port, + const uint8_t *data, size_t data_len) { + ip_addr_t dest_addr; + + if (!ip4addr_aton(ip_str, &dest_addr)) { + printf("Invalid IP address: %s\n", ip_str); + return -1; + } + + return udp_send_data(&dest_addr, dest_port, data, data_len); +} + +// Get current listen port +uint16_t udp_get_listen_port(void) { + return listen_port; +} + +// Check if UDP server is active +bool udp_is_server_active(void) { + return udp_server_active; +} + +// Process UDP (call from main loop) +void udp_poll(void) { + // lwIP polling is handled by cyw43_arch_poll() in wifi_handler + // This function can be used for any UDP-specific maintenance + + // Check if we need to restart server after WiFi reconnection + if (!udp_server_active && wifi_is_connected() && data_callback) { + printf("WiFi reconnected, restarting UDP server...\n"); + udp_server_start(listen_port, data_callback); + } +} + +// Cleanup UDP resources +void udp_deinit(void) { + udp_server_stop(); + printf("UDP handler deinitialized\n"); +} + +int main() { + stdio_init_all(); + sleep_ms(5000); + printf("Pico UDP Server Demo Starting...\n"); + + // Initialize WiFi + if (wifi_init() != 0) return -1; + if (wifi_connect(NULL, NULL) != 0) { + wifi_deinit(); + return -1; + } + + printf("IP Address: %s\n", wifi_get_ip_address()); + printf("%s\n", wifi_get_status_string()); + + // Initialize UDP server + if (udp_server_init(handle_udp_message) != 0) { + printf("Failed to start UDP server\n"); + wifi_deinit(); + return -1; + } + + printf("System ready - waiting for UDP messages...\n"); + + // Main loop + while (1) { + // Work goes here. + sleep_ms(10); + } + + // Cleanup - halts server in event of WiFi loss or loop break + udp_deinit(); + wifi_deinit(); + return 0; +} From 0280913bf3287b6c10a9fe3381b044d9f01c46de Mon Sep 17 00:00:00 2001 From: Ismail Mehmood Date: Sat, 28 Jun 2025 13:36:52 +0100 Subject: [PATCH 5/7] fix(removed redundant wifi check) --- pico_w/wifi/udp_server/picow_udp_server.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/pico_w/wifi/udp_server/picow_udp_server.c b/pico_w/wifi/udp_server/picow_udp_server.c index dc6cd5598..5f7768d37 100644 --- a/pico_w/wifi/udp_server/picow_udp_server.c +++ b/pico_w/wifi/udp_server/picow_udp_server.c @@ -233,11 +233,6 @@ int udp_server_start(uint16_t port, udp_data_callback_t callback) { return -1; } - // if (!wifi_is_connected()) { - // printf("WiFi not connected, cannot start UDP server\n"); - // return -1; - // } - // Create PCB udp_pcb = udp_new(); if (!udp_pcb) { From 516ef3012d4f08230b5046ee5c441e62f6597a12 Mon Sep 17 00:00:00 2001 From: Ismail Mehmood Date: Sat, 28 Jun 2025 13:42:11 +0100 Subject: [PATCH 6/7] feat(added polling for non threadsafe driver) --- pico_w/wifi/udp_server/picow_udp_server.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/pico_w/wifi/udp_server/picow_udp_server.c b/pico_w/wifi/udp_server/picow_udp_server.c index 5f7768d37..10e2cc953 100644 --- a/pico_w/wifi/udp_server/picow_udp_server.c +++ b/pico_w/wifi/udp_server/picow_udp_server.c @@ -12,6 +12,9 @@ #include #include +// Choose architecture +// #define PICO_CYW43_ARCH_POLL + // Connection timeout in ms #define WIFI_CONNECT_TIMEOUT_MS 30000 @@ -393,7 +396,12 @@ int main() { // Main loop while (1) { - // Work goes here. + #if PICO_CYW43_ARCH_POLL + wifi_poll(); + #else + // Do some work here. + sleep_ms(1000); + #endif sleep_ms(10); } From 275268edf71b9199e8ee4accb4a08bc526a2e3cf Mon Sep 17 00:00:00 2001 From: Ismail Mehmood Date: Sun, 29 Jun 2025 00:38:26 +0100 Subject: [PATCH 7/7] fix(debug errors with unused variables, implicit declarations and cmake typo) --- pico_w/wifi/CMakeLists.txt | 1 + .../python_test_udp/python_test_udp_client.py | 12 ++-- pico_w/wifi/udp_server/CMakeLists.txt | 6 +- pico_w/wifi/udp_server/picow_udp_server.c | 59 +++++++++++-------- 4 files changed, 44 insertions(+), 34 deletions(-) diff --git a/pico_w/wifi/CMakeLists.txt b/pico_w/wifi/CMakeLists.txt index 31797084b..8c403f3a2 100644 --- a/pico_w/wifi/CMakeLists.txt +++ b/pico_w/wifi/CMakeLists.txt @@ -17,6 +17,7 @@ else() add_subdirectory_exclude_platforms(tcp_client) add_subdirectory_exclude_platforms(tcp_server) add_subdirectory_exclude_platforms(udp_beacon) + add_subdirectory_exclude_platforms(udp_server) add_subdirectory_exclude_platforms(http_client) add_subdirectory_exclude_platforms(mqtt) diff --git a/pico_w/wifi/python_test_udp/python_test_udp_client.py b/pico_w/wifi/python_test_udp/python_test_udp_client.py index d8e4602af..861e21f9f 100644 --- a/pico_w/wifi/python_test_udp/python_test_udp_client.py +++ b/pico_w/wifi/python_test_udp/python_test_udp_client.py @@ -2,16 +2,16 @@ import time # === Configuration === -PICO_IP = "PI_IP_HERE" # Replace with your Pico's IP +PICO_IP = "PI_IP_HERE!" # Replace with your Pico's IP PICO_PORT = 12345 # Port Pico is listening on # === Data to send === data = { - "1.": "Message 1 received!", - "2.": "Message 2 received!", - "3.": "Message 3 received!", - "4.": "Message 4 received!", - "5.": "Message 5 received!" + "1": " Message 1 received!", + "2": " Message 2 received!", + "3": " Message 3 received!", + "4": " Message 4 received!", + "5": " Message 5 received!" } # === Create UDP socket === diff --git a/pico_w/wifi/udp_server/CMakeLists.txt b/pico_w/wifi/udp_server/CMakeLists.txt index 4ed1b06a5..734530cbd 100644 --- a/pico_w/wifi/udp_server/CMakeLists.txt +++ b/pico_w/wifi/udp_server/CMakeLists.txt @@ -18,10 +18,12 @@ target_link_libraries(picow_udp_server_background pico_add_extra_outputs(picow_udp_server_background) +pico_enable_stdio_usb(picow_udp_server_background 1) + # Manual polling add_executable(picow_udp_server_poll - picow_tcp_server.c + picow_udp_server.c ) target_compile_definitions(picow_udp_server_poll PRIVATE WIFI_SSID=\"${WIFI_SSID}\" @@ -35,7 +37,7 @@ target_link_libraries(picow_udp_server_poll pico_cyw43_arch_lwip_poll pico_stdlib ) + pico_add_extra_outputs(picow_udp_server_poll) pico_enable_stdio_usb(picow_udp_server_poll 1) -pico_enable_stdio_usb(picow_udp_server_background 1) diff --git a/pico_w/wifi/udp_server/picow_udp_server.c b/pico_w/wifi/udp_server/picow_udp_server.c index 10e2cc953..383f2f558 100644 --- a/pico_w/wifi/udp_server/picow_udp_server.c +++ b/pico_w/wifi/udp_server/picow_udp_server.c @@ -12,14 +12,14 @@ #include #include -// Choose architecture -// #define PICO_CYW43_ARCH_POLL +// define type for callback function +typedef void (*udp_data_callback_t)(const uint8_t *data, size_t data_len, + const ip_addr_t *src_addr, uint16_t src_port); // Connection timeout in ms #define WIFI_CONNECT_TIMEOUT_MS 30000 static bool wifi_connected = false; -static absolute_time_t connection_start_time; // Default UDP port #ifndef UDP_PORT @@ -44,6 +44,11 @@ int wifi_init(void) { return 0; } +// Set WiFi LED based on connection status +void wifi_update_led() { + cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, wifi_connected ? 1 : 0); +} + #define WIFI_CONNECT_TIMEOUT_MS 30000 int wifi_connect(const char *ssid, const char *password) { @@ -56,8 +61,6 @@ int wifi_connect(const char *ssid, const char *password) { cyw43_wifi_pm(&cyw43_state, CYW43_PERFORMANCE_PM); - int ssid_len = strlen(ssid); - if (cyw43_arch_wifi_connect_timeout_ms(WIFI_SSID, WIFI_PASSWORD, CYW43_AUTH_WPA2_AES_PSK, WIFI_CONNECT_TIMEOUT_MS)) { printf("failed to connect.\n"); @@ -156,11 +159,6 @@ void wifi_deinit(void) { printf("WiFi deinitialized\n"); } -// Set WiFi LED based on connection status -void wifi_update_led(void) { - cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, wifi_connected ? 1 : 0); -} - // Periodic WiFi maintenance (call from main loop) void wifi_poll(void) { // Update LED status @@ -189,6 +187,17 @@ static bool udp_server_active = false; // Buffer for incoming data static uint8_t rx_buffer[MAX_UDP_MSG_SIZE]; +void handle_udp_message(const unsigned char *data, unsigned int len, + const struct ip4_addr *addr, uint16_t port) { + if (len > 255) len = 255; // limit to safe buffer size + + char message[256] = {0}; + strncpy(message, (const char *)data, len); + message[len] = '\0'; + + printf("Received from %s:%u -> %s\n", ip4addr_ntoa(addr), port, message); +} + // Callback function for receiving UDP data static void udp_recv_callback(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) { @@ -215,22 +224,8 @@ static void udp_recv_callback(void *arg, struct udp_pcb *pcb, struct pbuf *p, } } -// Initialize UDP handler -int udp_server_init(udp_data_callback_t callback) { - printf("Initializing UDP handler...\n"); - - if (!callback) { - printf("Error: NULL callback passed to udp_server_init\n"); - return -1; - } - - data_callback = callback; // Save the app-level callback - return udp_server_start(UDP_PORT, callback); // Start server via saved port -} - - // Start UDP server on specified port -int udp_server_start(uint16_t port, udp_data_callback_t callback) { +static int udp_server_start(uint16_t port, udp_data_callback_t callback) { if (udp_server_active) { printf("UDP server already active\n"); return -1; @@ -260,6 +255,18 @@ int udp_server_start(uint16_t port, udp_data_callback_t callback) { return 0; } +// Initialize UDP handler +static int udp_server_init(udp_data_callback_t callback) { + printf("Initializing UDP handler...\n"); + + if (!callback) { + printf("Error: NULL callback passed to udp_server_init\n"); + return -1; + } + + data_callback = callback; // Save the app-level callback + return udp_server_start(UDP_PORT, callback); // Start server via saved port +} // Stop UDP server void udp_server_stop(void) { @@ -372,7 +379,7 @@ void udp_deinit(void) { int main() { stdio_init_all(); - sleep_ms(5000); + // sleep_ms(5000); // optional sleep for ease of testing. printf("Pico UDP Server Demo Starting...\n"); // Initialize WiFi