laser-server

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

main.c (5378B)


      1 #include "freertos/FreeRTOS.h"
      2 #include "freertos/task.h"
      3 #include "esp_mac.h"
      4 #include "esp_wifi.h"
      5 #include "esp_event.h"
      6 #include "esp_log.h"
      7 #include "nvs_flash.h"
      8 
      9 #include "lwip/err.h"
     10 #include "lwip/sockets.h"
     11 #include "lwip/sys.h"
     12 
     13 #define WIFI_SSID "laserbeam"
     14 #define WIFI_PASS ""
     15 #define WIFI_CHANNEL 1
     16 #define MAX_CONNECTIONS 1
     17 
     18 #define PORT 6969
     19 
     20 static const char* TAG = "laser-server";
     21 
     22 static void wifi_event_handler(
     23     void* arg,
     24     esp_event_base_t event_base,
     25     int32_t event_id,
     26     void* event_data
     27 )
     28 {
     29     if (event_id == WIFI_EVENT_AP_STACONNECTED) {
     30         wifi_event_ap_staconnected_t* event = (wifi_event_ap_staconnected_t*) event_data;
     31         ESP_LOGI(
     32             TAG,
     33            "station "MACSTR" join, AID=%d",
     34            MAC2STR(event->mac),
     35            event->aid
     36         );
     37     }
     38     else if (event_id == WIFI_EVENT_AP_STADISCONNECTED) {
     39         wifi_event_ap_stadisconnected_t* event = (wifi_event_ap_stadisconnected_t*) event_data;
     40         ESP_LOGI(
     41             TAG,
     42             "station "MACSTR" join, AID=%d, reason=%d",
     43             MAC2STR(event->mac),
     44             event->aid,
     45             event->reason
     46         );
     47     }
     48     else {
     49         ESP_LOGI(TAG, "unhandled wifi event: %ld\n", event_id);
     50     }
     51 }
     52 
     53 void wifi_init_softap(void) {
     54     esp_netif_create_default_wifi_ap();
     55 
     56     wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
     57     ESP_ERROR_CHECK(esp_wifi_init(&cfg));
     58 
     59     ESP_ERROR_CHECK(esp_event_handler_instance_register(
     60         WIFI_EVENT,
     61         ESP_EVENT_ANY_ID,
     62         &wifi_event_handler,
     63         NULL,
     64         NULL
     65     ));
     66 
     67     wifi_config_t wifi_config = {
     68         .ap = {
     69             .ssid = WIFI_SSID,
     70             .ssid_len = strlen(WIFI_SSID),
     71             .channel = WIFI_CHANNEL,
     72             .password = WIFI_PASS,
     73             .max_connection = MAX_CONNECTIONS,
     74             .authmode = WIFI_AUTH_WPA2_PSK,
     75             .pmf_cfg = {
     76                 .required = true,
     77             },
     78         },
     79     };
     80     if (strlen(WIFI_PASS) == 0) {
     81         wifi_config.ap.authmode = WIFI_AUTH_OPEN;
     82     }
     83 
     84     ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
     85     ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &wifi_config));
     86     ESP_ERROR_CHECK(esp_wifi_start());
     87 
     88     ESP_LOGI(
     89         TAG,
     90         "wifi_init_softap finished. SSID:%s password:%s channel:%d",
     91         WIFI_SSID,
     92         WIFI_PASS,
     93         WIFI_CHANNEL
     94     );
     95 }
     96 
     97 static void udp_server_task(void *params) {
     98     char rx_buffer[128];
     99     char addr_str[128];
    100     int addr_family = AF_INET;
    101     int ip_protocol = IPPROTO_IP;
    102 
    103     struct sockaddr_in dest_addr;
    104 
    105     while (true) {
    106         dest_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    107         dest_addr.sin_family = AF_INET;
    108         dest_addr.sin_port = htons(PORT);
    109 
    110         int sock = socket(addr_family, SOCK_DGRAM, ip_protocol);
    111         if (sock < 0) {
    112             ESP_LOGE(TAG, "unable to create socket: errno %d", errno);
    113             break;
    114         }
    115         ESP_LOGI(TAG, "socket created");
    116 
    117         struct timeval timeout;
    118         timeout.tv_sec = 10;
    119         timeout.tv_usec = 0;
    120         setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
    121 
    122         int err = bind(sock, (struct sockaddr*)&dest_addr, sizeof(dest_addr));
    123         if (err < 0) {
    124             ESP_LOGE(TAG, "socket unable to bind: errno %d", errno);
    125             break;
    126         }
    127         ESP_LOGI(TAG, "socket bound, port %d", PORT);
    128 
    129         struct sockaddr_storage source_addr;
    130         socklen_t socklen = sizeof(source_addr);
    131 
    132         while (true) {
    133             ESP_LOGI(TAG, "waiting for data");
    134 
    135             int len = recvfrom(
    136                 sock,
    137                 rx_buffer,
    138                 sizeof(rx_buffer) - 1,
    139                 0,
    140                 (struct sockaddr*)&source_addr,
    141                 &socklen
    142             );
    143             if (len < 0) {
    144                 ESP_LOGE(TAG, "recvfrom failed: errno %d", errno);
    145                 break;
    146             }
    147 
    148             if (source_addr.ss_family == PF_INET) {
    149                 inet_ntoa_r(
    150                     ((struct sockaddr_in*)&source_addr)->sin_addr,
    151                     addr_str,
    152                     sizeof(addr_str) - 1
    153                 );
    154             }
    155             else if (source_addr.ss_family == PF_INET6) {
    156                 inet6_ntoa_r(
    157                     ((struct sockaddr_in6*)&source_addr)->sin6_addr,
    158                     addr_str,
    159                     sizeof(addr_str) - 1
    160                 );
    161             }
    162 
    163             rx_buffer[len] = 0;
    164             ESP_LOGI(TAG, "received %d bytes from %s:", len, addr_str);
    165             ESP_LOGI(TAG, "%s", rx_buffer);
    166 
    167             int err = sendto(
    168                 sock,
    169                 rx_buffer,
    170                 len,
    171                 0,
    172                 (struct sockaddr*)&source_addr,
    173                 sizeof(source_addr)
    174             );
    175             if (err < 0) {
    176                 ESP_LOGE(TAG, "sendto failed: errno %d", errno);
    177                 break;
    178             }
    179         }
    180 
    181         if (sock != -1) {
    182             ESP_LOGE(TAG, "shutting down socket and restarting");
    183             shutdown(sock, 0);
    184             close(sock);
    185         }
    186     }
    187     vTaskDelete(NULL);
    188 }
    189 
    190 
    191 void app_main(void) {
    192     ESP_ERROR_CHECK(nvs_flash_init());
    193     ESP_ERROR_CHECK(esp_netif_init());
    194     ESP_ERROR_CHECK(esp_event_loop_create_default());
    195 
    196     wifi_init_softap();
    197 
    198     xTaskCreate(udp_server_task, "udp_server", 4096, NULL, 5, NULL);
    199 }