256 lines
7.9 KiB
C
256 lines
7.9 KiB
C
/*
|
|
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
/* Wi-Fi CSI console Example
|
|
|
|
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
|
|
|
Unless required by applicable law or agreed to in writing, this
|
|
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
CONDITIONS OF ANY KIND, either express or implied.
|
|
*/
|
|
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "freertos/event_groups.h"
|
|
#include "esp_event.h"
|
|
#include "esp_log.h"
|
|
#include "nvs_flash.h"
|
|
#include "esp_err.h"
|
|
#include "esp_console.h"
|
|
|
|
#include "esp_wifi.h"
|
|
#include "lwip/inet.h"
|
|
#include "lwip/netdb.h"
|
|
#include "lwip/sockets.h"
|
|
|
|
#include "mbedtls/base64.h"
|
|
#include "esp_radar.h"
|
|
|
|
#define RX_BUFFER_SIZE 1460
|
|
#define KEEPALIVE_IDLE 1
|
|
#define KEEPALIVE_INTERVAL 1
|
|
#define KEEPALIVE_COUNT 3
|
|
typedef union {
|
|
struct {
|
|
const char *type;
|
|
const char *id;
|
|
const char *timestamp;
|
|
const char *action_id;
|
|
const char *action;
|
|
const char *mac;
|
|
const char *rssi;
|
|
const char *rate;
|
|
const char *sig_mode;
|
|
const char *mcs;
|
|
const char *bandwidth;
|
|
const char *smoothing;
|
|
const char *not_sounding;
|
|
const char *aggregation;
|
|
const char *stbc;
|
|
const char *fec_coding;
|
|
const char *sgi;
|
|
const char *noise_floor;
|
|
const char *ampdu_cnt;
|
|
const char *channel;
|
|
const char *secondary_channel;
|
|
const char *local_timestamp;
|
|
const char *ant;
|
|
const char *sig_len;
|
|
const char *rx_state;
|
|
const char *len;
|
|
const char *first_word;
|
|
const char *data;
|
|
};
|
|
const char *data_array[28];
|
|
} csi_data_str_t;
|
|
|
|
static char *TAG = "radar_evaluate";
|
|
static char g_wifi_radar_cb_ctx[32] = {0};
|
|
static TaskHandle_t g_tcp_server_task_handle = NULL;
|
|
|
|
static void csi_info_analysis(char *data, size_t size)
|
|
{
|
|
uint8_t column = 0;
|
|
const char *s = ",";
|
|
char *token = NULL;
|
|
csi_data_str_t *csi_data = malloc(sizeof(csi_data_str_t));
|
|
|
|
token = strtok(data, s);
|
|
|
|
do {
|
|
csi_data->data_array[column++] = token;
|
|
token = strtok(NULL, s);
|
|
} while (token != NULL && column < 28);
|
|
|
|
if (token != NULL) {
|
|
ESP_LOGE(TAG, "data error, temp_data: %s", data);
|
|
}
|
|
|
|
wifi_csi_filtered_info_t *filtered_info = malloc(sizeof(wifi_csi_filtered_info_t) + 52 * 2);
|
|
mbedtls_base64_decode((uint8_t *)filtered_info->valid_data, 52 * 2, (size_t *)&filtered_info->valid_len, (uint8_t *)csi_data->data, strlen(csi_data->data));
|
|
filtered_info->rx_ctrl_info.timestamp = atoi(csi_data->local_timestamp);
|
|
strcpy(g_wifi_radar_cb_ctx, csi_data->timestamp);
|
|
// ESP_LOGI(TAG,"count: %s, timestamp: %d", csi_data->id, filtered_info->rx_ctrl.timestamp);
|
|
|
|
extern esp_err_t csi_data_push(wifi_csi_filtered_info_t *info);
|
|
csi_data_push(filtered_info);
|
|
|
|
free(csi_data);
|
|
}
|
|
|
|
static void tcp_server_task(void *arg)
|
|
{
|
|
char addr_str[128];
|
|
int addr_family = AF_INET;
|
|
int ip_protocol = 0;
|
|
int keepAlive = 1;
|
|
int keepIdle = KEEPALIVE_IDLE;
|
|
int keepInterval = KEEPALIVE_INTERVAL;
|
|
int keepCount = KEEPALIVE_COUNT;
|
|
struct sockaddr_storage dest_addr;
|
|
uint32_t port = (uint32_t)arg;
|
|
|
|
if (addr_family == AF_INET) {
|
|
struct sockaddr_in *dest_addr_ip4 = (struct sockaddr_in *)&dest_addr;
|
|
dest_addr_ip4->sin_addr.s_addr = htonl(INADDR_ANY);
|
|
dest_addr_ip4->sin_family = AF_INET;
|
|
dest_addr_ip4->sin_port = htons(port);
|
|
ip_protocol = IPPROTO_IP;
|
|
}
|
|
|
|
int listen_sock = socket(addr_family, SOCK_STREAM, ip_protocol);
|
|
|
|
if (listen_sock < 0) {
|
|
ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
|
|
vTaskDelete(NULL);
|
|
return;
|
|
}
|
|
|
|
int opt = 1;
|
|
setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
|
|
|
|
ESP_LOGI(TAG, "Socket created");
|
|
|
|
int err = bind(listen_sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
|
|
|
|
if (err != 0) {
|
|
ESP_LOGE(TAG, "Socket unable to bind: errno %d, errno_str: %s", errno, strerror(errno));
|
|
ESP_LOGE(TAG, "IPPROTO: %d", addr_family);
|
|
goto CLEAN_UP;
|
|
}
|
|
|
|
ESP_LOGI(TAG, "Socket bound, port %d", port);
|
|
|
|
err = listen(listen_sock, 1);
|
|
|
|
if (err != 0) {
|
|
ESP_LOGE(TAG, "Error occurred during listen: errno %d", errno);
|
|
goto CLEAN_UP;
|
|
}
|
|
|
|
while (1) {
|
|
ESP_LOGI(TAG, "Socket listening");
|
|
struct sockaddr_storage source_addr; // Large enough for both IPv4 or IPv6
|
|
socklen_t addr_len = sizeof(source_addr);
|
|
int sock = accept(listen_sock, (struct sockaddr *)&source_addr, &addr_len);
|
|
|
|
if (sock < 0) {
|
|
ESP_LOGE(TAG, "Unable to accept connection: errno %d", errno);
|
|
break;
|
|
}
|
|
|
|
// Set tcp keepalive option
|
|
setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &keepAlive, sizeof(int));
|
|
setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE, &keepIdle, sizeof(int));
|
|
setsockopt(sock, IPPROTO_TCP, TCP_KEEPINTVL, &keepInterval, sizeof(int));
|
|
setsockopt(sock, IPPROTO_TCP, TCP_KEEPCNT, &keepCount, sizeof(int));
|
|
|
|
// Convert ip address to string
|
|
if (source_addr.ss_family == PF_INET) {
|
|
inet_ntoa_r(((struct sockaddr_in *)&source_addr)->sin_addr, addr_str, sizeof(addr_str) - 1);
|
|
}
|
|
|
|
ESP_LOGI(TAG, "Socket accepted ip address: %s", addr_str);
|
|
|
|
int len;
|
|
char *rx_buffer = malloc(RX_BUFFER_SIZE);
|
|
size_t buf_size = 0;
|
|
|
|
esp_radar_config_t radar_config = {0};
|
|
esp_radar_get_config(&radar_config);
|
|
radar_config.dec_config.wifi_radar_cb_ctx = g_wifi_radar_cb_ctx;
|
|
esp_radar_change_config(&radar_config);
|
|
|
|
do {
|
|
len = recv(sock, rx_buffer + buf_size, RX_BUFFER_SIZE - buf_size - 1, 0);
|
|
|
|
// ESP_LOGW(TAG, "len: %d, rx_buffer: %s", len, rx_buffer);
|
|
if (len < 0) {
|
|
ESP_LOGE(TAG, "Error occurred during receiving: errno %d", errno);
|
|
|
|
} else if (len == 0) {
|
|
ESP_LOGW(TAG, "Connection closed");
|
|
} else {
|
|
buf_size += len;
|
|
rx_buffer[buf_size] = 0; // Null-terminate whatever is received and treat it like a string
|
|
// ESP_LOGI(TAG, "Received %d, buf_size: %d", len, buf_size);
|
|
|
|
while (buf_size > 250) {
|
|
char *begin = strstr(rx_buffer, "CSI_DATA");
|
|
char *end = strstr(rx_buffer, "\n");
|
|
ssize_t size = end - begin;
|
|
|
|
// ESP_LOGW("TAG", "begin: %p, end: %p, size: %d", begin, end, size);
|
|
// ESP_LOGW(TAG, "size: %d, received: %d, buf_size: %d", size, len, buf_size);
|
|
|
|
if (begin && end && size > 250) {
|
|
begin[size] = '\0';
|
|
csi_info_analysis(begin, size);
|
|
}
|
|
|
|
if (end) {
|
|
buf_size -= (end + 1 - rx_buffer);
|
|
memcpy(rx_buffer, end + 1, buf_size);
|
|
memset(rx_buffer + buf_size, 0, end + 1 - rx_buffer);
|
|
}
|
|
|
|
if (begin && !end) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} while (len > 0);
|
|
|
|
shutdown(sock, 0);
|
|
close(sock);
|
|
free(rx_buffer);
|
|
|
|
ESP_LOGW(TAG, "Socket close: %s", addr_str);
|
|
|
|
vTaskDelay(pdMS_TO_TICKS(1000));
|
|
esp_radar_get_config(&radar_config);
|
|
radar_config.dec_config.wifi_radar_cb_ctx = NULL;
|
|
esp_radar_change_config(&radar_config);
|
|
}
|
|
|
|
CLEAN_UP:
|
|
close(listen_sock);
|
|
g_tcp_server_task_handle = NULL;
|
|
vTaskDelete(NULL);
|
|
}
|
|
|
|
esp_err_t radar_evaluate_server(uint32_t port)
|
|
{
|
|
if (!g_tcp_server_task_handle) {
|
|
xTaskCreate(tcp_server_task, "tcp_server", 4 * 1024, (void *)port, 0, &g_tcp_server_task_handle);
|
|
}
|
|
|
|
return ESP_OK;
|
|
}
|