laser-server

git clone git://git.christianermann.dev/laser-server
Log | Files | Refs

commit 77eecb30568f1edf16c9eb5ef00f68e9b554572f
parent d233aae48f469cbb1c6a071d2dea3e6d5298acea
Author: Christian Ermann <christianermann@gmail.com>
Date:   Sat, 24 May 2025 19:07:39 -0700

Add Wifi AP and UDP server

Diffstat:
ACMakeLists.txt | 4++++
Amain/CMakeLists.txt | 4++++
Amain/main.c | 199+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 207 insertions(+), 0 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(laser-server) diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt @@ -0,0 +1,4 @@ +idf_component_register( + SRCS "main.c" + INCLUDE_DIRS "" +) diff --git a/main/main.c b/main/main.c @@ -0,0 +1,199 @@ +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_mac.h" +#include "esp_wifi.h" +#include "esp_event.h" +#include "esp_log.h" +#include "nvs_flash.h" + +#include "lwip/err.h" +#include "lwip/sockets.h" +#include "lwip/sys.h" + +#define WIFI_SSID "laserbeam" +#define WIFI_PASS "" +#define WIFI_CHANNEL 1 +#define MAX_CONNECTIONS 1 + +#define PORT 6969 + +static const char* TAG = "laser-server"; + +static void wifi_event_handler( + void* arg, + esp_event_base_t event_base, + int32_t event_id, + void* event_data +) +{ + if (event_id == WIFI_EVENT_AP_STACONNECTED) { + wifi_event_ap_staconnected_t* event = (wifi_event_ap_staconnected_t*) event_data; + ESP_LOGI( + TAG, + "station "MACSTR" join, AID=%d", + MAC2STR(event->mac), + event->aid + ); + } + else if (event_id == WIFI_EVENT_AP_STADISCONNECTED) { + wifi_event_ap_stadisconnected_t* event = (wifi_event_ap_stadisconnected_t*) event_data; + ESP_LOGI( + TAG, + "station "MACSTR" join, AID=%d, reason=%d", + MAC2STR(event->mac), + event->aid, + event->reason + ); + } + else { + ESP_LOGI(TAG, "unhandled wifi event: %ld\n", event_id); + } +} + +void wifi_init_softap(void) { + esp_netif_create_default_wifi_ap(); + + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + + ESP_ERROR_CHECK(esp_event_handler_instance_register( + WIFI_EVENT, + ESP_EVENT_ANY_ID, + &wifi_event_handler, + NULL, + NULL + )); + + wifi_config_t wifi_config = { + .ap = { + .ssid = WIFI_SSID, + .ssid_len = strlen(WIFI_SSID), + .channel = WIFI_CHANNEL, + .password = WIFI_PASS, + .max_connection = MAX_CONNECTIONS, + .authmode = WIFI_AUTH_WPA2_PSK, + .pmf_cfg = { + .required = true, + }, + }, + }; + if (strlen(WIFI_PASS) == 0) { + wifi_config.ap.authmode = WIFI_AUTH_OPEN; + } + + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP)); + ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &wifi_config)); + ESP_ERROR_CHECK(esp_wifi_start()); + + ESP_LOGI( + TAG, + "wifi_init_softap finished. SSID:%s password:%s channel:%d", + WIFI_SSID, + WIFI_PASS, + WIFI_CHANNEL + ); +} + +static void udp_server_task(void *params) { + char rx_buffer[128]; + char addr_str[128]; + int addr_family = AF_INET; + int ip_protocol = IPPROTO_IP; + + struct sockaddr_in dest_addr; + + while (true) { + dest_addr.sin_addr.s_addr = htonl(INADDR_ANY); + dest_addr.sin_family = AF_INET; + dest_addr.sin_port = htons(PORT); + + int sock = socket(addr_family, SOCK_DGRAM, ip_protocol); + if (sock < 0) { + ESP_LOGE(TAG, "unable to create socket: errno %d", errno); + break; + } + ESP_LOGI(TAG, "socket created"); + + struct timeval timeout; + timeout.tv_sec = 10; + timeout.tv_usec = 0; + setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); + + int err = bind(sock, (struct sockaddr*)&dest_addr, sizeof(dest_addr)); + if (err < 0) { + ESP_LOGE(TAG, "socket unable to bind: errno %d", errno); + break; + } + ESP_LOGI(TAG, "socket bound, port %d", PORT); + + struct sockaddr_storage source_addr; + socklen_t socklen = sizeof(source_addr); + + while (true) { + ESP_LOGI(TAG, "waiting for data"); + + int len = recvfrom( + sock, + rx_buffer, + sizeof(rx_buffer) - 1, + 0, + (struct sockaddr*)&source_addr, + &socklen + ); + if (len < 0) { + ESP_LOGE(TAG, "recvfrom failed: errno %d", errno); + break; + } + + if (source_addr.ss_family == PF_INET) { + inet_ntoa_r( + ((struct sockaddr_in*)&source_addr)->sin_addr, + addr_str, + sizeof(addr_str) - 1 + ); + } + else if (source_addr.ss_family == PF_INET6) { + inet6_ntoa_r( + ((struct sockaddr_in6*)&source_addr)->sin6_addr, + addr_str, + sizeof(addr_str) - 1 + ); + } + + rx_buffer[len] = 0; + ESP_LOGI(TAG, "received %d bytes from %s:", len, addr_str); + ESP_LOGI(TAG, "%s", rx_buffer); + + int err = sendto( + sock, + rx_buffer, + len, + 0, + (struct sockaddr*)&source_addr, + sizeof(source_addr) + ); + if (err < 0) { + ESP_LOGE(TAG, "sendto failed: errno %d", errno); + break; + } + } + + if (sock != -1) { + ESP_LOGE(TAG, "shutting down socket and restarting"); + shutdown(sock, 0); + close(sock); + } + } + vTaskDelete(NULL); +} + + +void app_main(void) { + ESP_ERROR_CHECK(nvs_flash_init()); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + wifi_init_softap(); + + xTaskCreate(udp_server_task, "udp_server", 4096, NULL, 5, NULL); +}