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:
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);
+}