feat: Initial esp32-hacking project with firmware sources and docs
This commit is contained in:
11
esp-radar/connect_rainmaker/CMakeLists.txt
Normal file
11
esp-radar/connect_rainmaker/CMakeLists.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
# The following lines of boilerplate have to be in your project's CMakeLists
|
||||
# in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
add_compile_options(-fdiagnostics-color=always)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
string(REGEX REPLACE ".*/\(.*\)" "\\1" CURDIR ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
project(${CURDIR})
|
||||
|
||||
git_describe(PROJECT_VERSION ${COMPONENT_DIR})
|
||||
message("Project commit: " ${PROJECT_VERSION})
|
||||
79
esp-radar/connect_rainmaker/README.md
Normal file
79
esp-radar/connect_rainmaker/README.md
Normal file
@@ -0,0 +1,79 @@
|
||||
# Adding Wi-Fi CSI Functionality in ESP RainMaker [[中文]](./README_cn.md)
|
||||
|
||||
## Build and Flashing Instructions
|
||||
Follow the ESP RainMaker documentation [Getting Started](https://rainmaker.espressif.com/docs/get-started.html) section to build and flash the firmware.
|
||||
|
||||
## How to Use This Example
|
||||
|
||||
### Parameter Description
|
||||
- **someone_status**: false - no one, true - someone
|
||||
- **someone_timeout**: If someone moves within this time in the room, it will be marked as someone present. Time is in seconds.
|
||||
- **move_status**: false - no movement, true - movement
|
||||
- **move_count**: Number of times movement is detected between the last ESP RainMaker report.
|
||||
- **move_threshold**: Threshold value to determine if there is movement.
|
||||
- **filter_window**: Size of the buffer queue for Wi-Fi CSI waveform jitter values, used for filtering outliers.
|
||||
- **filter_count**: If the jitter value of the Wi-Fi CSI waveform exceeds the `move_threshold` for `filter_count` times within the buffer queue, it is marked as movement detected.
|
||||
- **threshold_calibrate**: Enable threshold auto-calibration.
|
||||
- **threshold_calibrate_timeout**: Auto-calibration timeout, in seconds.
|
||||
|
||||
### App Version
|
||||
- ESP RainMaker App: [v2.11.1](https://m.apkpure.com/p/com.espressif.rainmaker)+
|
||||
> Note: `ESP RainMaker` App version before 2.11.1 does not support `time series` function, `move_count` cannot be displayed normally
|
||||
|
||||
### App Operation
|
||||
1. Open the RainMaker App.
|
||||
2. Click on `+` to add a device.
|
||||
3. Wait for the device to connect to the cloud.
|
||||
4. Enable `threshold_calibrate` to perform auto-calibration. Ensure there is no one or no movement in the room during calibration.
|
||||
5. After calibration, the threshold value for movement detection will be displayed in `move_threshold`, and `move_status` will become true when movement is detected.
|
||||
|
||||
### Device
|
||||
- [x] ESP32-S3-DevKitC-1
|
||||
- [x] ESP32-C3-DevKitC
|
||||
|
||||
### Device Operation
|
||||
1. **Factory Reset**: Press and hold the `BOOT` button for more than 5 seconds to reset the development board to factory defaults.
|
||||
|
||||
## Device Status
|
||||
- Human Movement Detection
|
||||
- Green LED indicates movement detected in the room.
|
||||
- White LED indicates no movement detected in the room.
|
||||
|
||||
- Human Presence Detection
|
||||
> The current algorithm for human presence detection is not ideal. Therefore, the presence of someone is determined by whether there has been any movement within 1 minute. If there is movement, it is considered someone is present; otherwise, it is considered no one is present.
|
||||
- LED lights up when there is someone in the room.
|
||||
- LED turns off when there is no one in the room.
|
||||
|
||||
- Human Movement Detection Threshold
|
||||
> - The threshold for human movement detection can be set via the mobile app or obtained through auto-calibration. If not set, the default value will be used.
|
||||
> - During calibration, ensure there is no one or no movement in the room. After calibration, the detection sensitivity will be increased. However, if there is movement in the room, it may result in false detection. Therefore, it is recommended to perform calibration when there is no one in the room.
|
||||
> - The calibrated threshold will be saved in NVS and will be used after the next reboot.
|
||||
- During human movement threshold calibration, the LED will flash yellow.
|
||||
|
||||
## Common Issues
|
||||
|
||||
### RainMaker Reporting Failure
|
||||
------
|
||||
- **Issue**: The device-side logs show the following error:
|
||||
```shell
|
||||
E (399431) esp_rmaker_mqtt: Out of MQTT Budget. Dropping publish message.
|
||||
```
|
||||
|
||||
- **Cause**: The amount of data being reported by the device exceeds the limit of `ESP RainMaker`.
|
||||
|
||||
------
|
||||
- **Issue**: Continuous movement detection without actual movement or the device does not detect any movement.
|
||||
|
||||
- **Solution**:
|
||||
1. Incorrect human movement detection threshold leading to false recognition.
|
||||
- The default Wi-Fi CSI human movement detection threshold may not meet the actual requirements. Adjust it according to the actual situation or enable auto-calibration through the mobile app.
|
||||
- The default outlier filtering window size for Wi-Fi CSI may not meet the actual requirements. Adjust it according to the actual situation through the mobile app.
|
||||
|
||||
2. Unstable network causing inaccurate detection.
|
||||
- Check if it works properly after replacing the router.
|
||||
- Try placing the router in a more suitable location.
|
||||
|
||||
3. The above methods still cannot solve the problem, modify the LOG level and submit [issue](https://github.com/espressif/esp-csi/issues) on github
|
||||
```c
|
||||
esp_log_level_set("esp_radar", ESP_LOG_DEBUG);
|
||||
```
|
||||
78
esp-radar/connect_rainmaker/README_cn.md
Normal file
78
esp-radar/connect_rainmaker/README_cn.md
Normal file
@@ -0,0 +1,78 @@
|
||||
# ESP RainMaker 中添加 Wi-Fi CSI 功能 [[English]](./README.md)
|
||||
|
||||
## 编译下载
|
||||
按照 ESP RainMaker 文档 [入门](https://rainmaker.espressif.com/docs/get-started.html) 部分构建和烧录固件
|
||||
|
||||
## 如何使用这个例子
|
||||
### 参数说明
|
||||
- **someone_status**: false - 无人, true - 有人
|
||||
- **someone_timeout**: 房间内在此时间内有人移动则标识为有人,单位为秒
|
||||
- **move_status**: false - 无人移动, true - 有人移动
|
||||
- **move_count**: 与上一次上报 `ESP RainMaker` 之间检测到的有人移动的次数
|
||||
- **move_threshold**: 用于判断是否有人在移动的阈值
|
||||
- **filter_window**: `Wi-Fi CSI` 的波形的抖动值的缓冲队列的大小,用于过滤异常值
|
||||
- **filter_count**: 在波形的抖动值的缓冲队列内,当检测到 `filter_count` 次,`Wi-Fi CSI` 的波形的抖动值大于 `move_threshold`,标记为有人移动
|
||||
- **threshold_calibrate**: 是否使能自校准
|
||||
- **threshold_calibrate_timeout**: 自校准超时时间,单位为秒
|
||||
|
||||
### App 版本
|
||||
- ESP RainMaker App: [v2.11.1](https://m.apkpure.com/p/com.espressif.rainmaker)+
|
||||
> 注: `ESP RainMaker` App 2.11.1 版本之前的版本不支持 `time series` 功能,`move_count` 无法正常显示
|
||||
|
||||
### APP 操作
|
||||
1. 打开 RainMaker App
|
||||
2. 点击 `+` 添加设备
|
||||
3. 等待设备连接到云端
|
||||
4. 点击 `threshold_calibrate` 使能自校准,校准时需要保证房间内无人或人不移动
|
||||
5. 校准完成后,有人移动的阈值会显示在 `move_threshold` 中,此时检测到有人移动 move_status 会变为 true
|
||||
|
||||
### 设备
|
||||
- [x] ESP32-S3-DevKitC-1
|
||||
- [x] ESP32-C3-DevKitC
|
||||
|
||||
### 设备操作
|
||||
1. **恢复出厂设置**:按住 `BOOT` 按钮 5 秒以上可将开发板重置为出厂默认设置
|
||||
|
||||
## 设备状态
|
||||
- 人体移动检测
|
||||
- 房间内有人移动: LED 亮绿灯
|
||||
- 房间内无人移动: LED 亮白灯
|
||||
|
||||
- 人体存在检测
|
||||
> 当前算法人体存在检测效果不理想,因此判断是否有人移动的依据是:1 分钟内是否有人移动,如果有人移动则认为有人存在,否则认为无人存在
|
||||
- 房间内有人: LED 亮起
|
||||
- 房间内无人: LED 熄灭
|
||||
|
||||
- 人体移动检测阈值
|
||||
> - 人体移动检测阈值可以通过手机 App 设置也可以通过自校准获取,如果没有设置则使用默认值
|
||||
> - 校准时需要保证房间内无人或人不移动,校准后检测灵敏度会提高,但是如果房间内有人移动则会导致误检测,因此建议在房间内无人时进行校准
|
||||
> - 校准后将会保存在 NVS 中,下次重启后会使用保存的阈值
|
||||
- 进行人体移动阈值校准时,LED 黄色闪烁
|
||||
|
||||
## 常见问题
|
||||
|
||||
### RainMaker 上报失败
|
||||
|
||||
------
|
||||
- **问题**: 设备端日志上打印如下错误
|
||||
```shell
|
||||
E (399431) esp_rmaker_mqtt: Out of MQTT Budget. Dropping publish message.
|
||||
```
|
||||
- **原因**: 设备端上报的数据量超过了 `ESP RainMaker` 的限制
|
||||
|
||||
------
|
||||
- **问题**: 一直检测到有人移动但是实际上没有人移动,或者设备端一直检测不到人移动
|
||||
|
||||
- **解决方式**:
|
||||
1. 人体移动检测阈值不对导致误识别
|
||||
- Wi-Fi CSI 默认人体移动检测阈值无法满足实际需求,需要根据实际情况调整或使能自校准,可以通过手机 App 设置
|
||||
- Wi-Fi CSI 默认的离群点过滤窗口大小无法满足实际需求,需要根据实际情况调整,可以通过手机 App 设置
|
||||
|
||||
2. 网络不稳定导致检测不准确
|
||||
- 更换路由器后是否能正常工作
|
||||
- 是否可以尝试将路由器放置在更合适的位置
|
||||
|
||||
3. 以上方式仍旧无法解决,修改 LOG 等级,在 github 上提交 [issue](https://github.com/espressif/esp-csi/issues)
|
||||
```c
|
||||
esp_log_level_set("esp_radar", ESP_LOG_DEBUG);
|
||||
```
|
||||
3
esp-radar/connect_rainmaker/main/CMakeLists.txt
Normal file
3
esp-radar/connect_rainmaker/main/CMakeLists.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
idf_component_register(SRC_DIRS "."
|
||||
INCLUDE_DIRS ".")
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
|
||||
481
esp-radar/connect_rainmaker/main/app_main.c
Normal file
481
esp-radar/connect_rainmaker/main/app_main.c
Normal file
@@ -0,0 +1,481 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
#include "freertos/timers.h"
|
||||
|
||||
#include <esp_log.h>
|
||||
#include <nvs_flash.h>
|
||||
|
||||
#include "ping/ping_sock.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/netdb.h"
|
||||
#include "lwip/sockets.h"
|
||||
|
||||
#include <esp_rmaker_core.h>
|
||||
#include <esp_rmaker_standard_params.h>
|
||||
#include <esp_rmaker_standard_devices.h>
|
||||
#include <esp_rmaker_schedule.h>
|
||||
#include <esp_rmaker_scenes.h>
|
||||
#include <esp_rmaker_utils.h>
|
||||
#include <esp_rmaker_core.h>
|
||||
#include <esp_rmaker_common_events.h>
|
||||
#include <esp_rmaker_standard_types.h>
|
||||
|
||||
#include <app_wifi.h>
|
||||
#include <app_reset.h>
|
||||
#include "led_strip.h"
|
||||
#include <iot_button.h>
|
||||
|
||||
#include "esp_radar.h"
|
||||
#include "esp_ping.h"
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32C5
|
||||
#define WS2812_GPIO 27
|
||||
#elif CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32C61
|
||||
#define WS2812_GPIO 8
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
#define WS2812_GPIO 38
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#define WS2812_GPIO 18
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||
#define WS2812_GPIO 8
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32C3
|
||||
#define BUTTON_GPIO GPIO_NUM_8
|
||||
#else
|
||||
#define BUTTON_GPIO GPIO_NUM_0
|
||||
#endif
|
||||
|
||||
#define BUTTON_WIFI_RESET_TIMEOUT 3
|
||||
#define BUTTON_FACTORY_RESET_TIMEOUT 5
|
||||
#define AUTO_CALIBRATE_RAPORT_INTERVAL 5
|
||||
|
||||
#define RADAR_PING_DATA_INTERVAL 10
|
||||
#define RADAR_DETECT_BUFF_MAX_SIZE 16
|
||||
#define RADAR_PARAM_SOMEONE_STATUS "someone_status"
|
||||
#define RADAR_PARAM_SOMEONE_TIMEOUT "someone_timeout"
|
||||
#define RADAR_PARAM_MOVE_STATUS "move_status"
|
||||
#define RADAR_PARAM_MOVE_COUNT "move_count"
|
||||
#define RADAR_PARAM_MOVE_THRESHOLD "move_threshold"
|
||||
#define RADAR_PARAM_FILTER_WINDOW "filter_window"
|
||||
#define RADAR_PARAM_FILTER_COUNT "filter_count"
|
||||
#define RADAR_PARAM_THRESHOLD_CALIBRATE "threshold_calibrate"
|
||||
#define RADAR_PARAM_THRESHOLD_CALIBRATE_TIMEOUT "threshold_calibrate_timeout"
|
||||
static led_strip_handle_t led_strip;
|
||||
typedef struct {
|
||||
bool threshold_calibrate; /**< Self-calibration acquisition, the most suitable threshold, calibration is to ensure that no one is in the room */
|
||||
uint8_t threshold_calibrate_timeout; /**< Calibration timeout, the unit is second */
|
||||
float someone_timeout; /**< The unit is second, how long no one moves in the room is marked as no one */
|
||||
float move_threshold; /**< Use to determine whether someone is moving */
|
||||
uint8_t filter_window; /**< window without filtering outliers */
|
||||
uint8_t filter_count; /**< Detect multiple times within the outlier window greater than move_threshold to mark as someone moving */
|
||||
} radar_detect_config_t;
|
||||
|
||||
static const char *TAG = "app_main";
|
||||
static float g_someone_threshold = 0.002;
|
||||
static nvs_handle_t g_nvs_handle = 0;
|
||||
static int32_t g_auto_calibrate_timerleft = 0;
|
||||
static TimerHandle_t g_auto_calibrate_timerhandle = NULL;
|
||||
static esp_rmaker_device_t *radar_device = NULL;
|
||||
static radar_detect_config_t g_detect_config = {
|
||||
.someone_timeout = 3 * 60,
|
||||
.move_threshold = 0.002,
|
||||
.filter_window = 5,
|
||||
.filter_count = 2,
|
||||
.threshold_calibrate_timeout = 60,
|
||||
};
|
||||
|
||||
static esp_err_t ping_router_start(uint32_t interval_ms)
|
||||
{
|
||||
static esp_ping_handle_t ping_handle = NULL;
|
||||
esp_ping_config_t config = ESP_PING_DEFAULT_CONFIG();
|
||||
config.count = 0;
|
||||
config.timeout_ms = 1000;
|
||||
config.data_size = 1;
|
||||
config.interval_ms = interval_ms;
|
||||
|
||||
/**
|
||||
* @brief Get the Router IP information from the esp-netif
|
||||
*/
|
||||
esp_netif_ip_info_t local_ip;
|
||||
esp_netif_get_ip_info(esp_netif_get_handle_from_ifkey("WIFI_STA_DEF"), &local_ip);
|
||||
ESP_LOGI(TAG, "Ping: got ip:" IPSTR ", gw: " IPSTR, IP2STR(&local_ip.ip), IP2STR(&local_ip.gw));
|
||||
config.target_addr.u_addr.ip4.addr = ip4_addr_get_u32(&local_ip.gw);
|
||||
config.target_addr.type = ESP_IPADDR_TYPE_V4;
|
||||
|
||||
// esp_ping_get_target(PING_TARGET_IP_ADDRESS, &config.target_addr, sizeof(ip_addr_t));
|
||||
esp_ping_callbacks_t cbs = { 0 };
|
||||
esp_ping_new_session(&config, &cbs, &ping_handle);
|
||||
esp_ping_start(ping_handle);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void radar_cb(void *ctx, const wifi_radar_info_t *info)
|
||||
{
|
||||
bool someone_status = false;
|
||||
bool move_status = false;
|
||||
|
||||
/**
|
||||
* @brief Filtering outliers is more accurate using detection,
|
||||
* but it takes more time, lower sensitive to the environment
|
||||
*
|
||||
* @note Current algorithm limitations:
|
||||
* 1. Calibration is required to detect whether there are people in the room;
|
||||
* 2. No calibration is required to detect movement, but the sensitivity is higher after calibration
|
||||
*/
|
||||
static uint32_t s_buff_count = 0;
|
||||
static float s_buff_jitter[RADAR_DETECT_BUFF_MAX_SIZE] = {0};
|
||||
uint32_t buff_max_size = g_detect_config.filter_window;
|
||||
uint32_t buff_outliers_num = g_detect_config.filter_count;
|
||||
|
||||
s_buff_jitter[s_buff_count % buff_max_size] = info->waveform_jitter;
|
||||
|
||||
if (++s_buff_count < buff_max_size) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0, move_count = 0; i < buff_max_size; i++) {
|
||||
if (s_buff_jitter[i] > g_detect_config.move_threshold) {
|
||||
move_count++;
|
||||
}
|
||||
|
||||
if (move_count >= buff_outliers_num) {
|
||||
move_status = true;
|
||||
}
|
||||
}
|
||||
|
||||
someone_status = (info->waveform_jitter > g_someone_threshold) ? true : false;
|
||||
static uint32_t s_count = 0;
|
||||
|
||||
if (!s_count++) {
|
||||
ESP_LOGI(TAG, "================ RADAR RECV ================");
|
||||
ESP_LOGI(TAG, "type,sequence,timestamp,waveform_wander,someone_threshold,someone_status,waveform_jitter,move_threshold,move_status\n");
|
||||
}
|
||||
|
||||
ESP_LOGI("RADAR_DADA", "RADAR_DADA,%d,%u,%.6f,%.6f,%d,%.6f,%.6f,%d",
|
||||
s_count, esp_log_timestamp(),
|
||||
info->waveform_wander, g_someone_threshold, someone_status,
|
||||
info->waveform_jitter, g_detect_config.move_threshold, move_status);
|
||||
|
||||
/* Calibrate the environment, LED will flash yellow */
|
||||
if (g_detect_config.threshold_calibrate) {
|
||||
static bool led_status = false;
|
||||
|
||||
if (led_status) {
|
||||
led_strip_set_pixel(led_strip, 0, 0, 0);
|
||||
} else {
|
||||
led_strip_set_pixel(led_strip, 0, 255, 255, 0);
|
||||
}
|
||||
led_strip_refresh(led_strip);
|
||||
led_status = !led_status;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Use LED and LOG to display the detection results
|
||||
* 1. Someone moves in the room, LED will flash green
|
||||
* 2. No one moves in the room, LED will flash white
|
||||
* 3. No one in the room, LED will turn off
|
||||
*/
|
||||
static uint32_t s_last_move_time = 0;
|
||||
static bool s_last_move_status = false;
|
||||
|
||||
if (esp_log_timestamp() - s_last_move_time < g_detect_config.someone_timeout * 1000) {
|
||||
someone_status = true;
|
||||
} else {
|
||||
someone_status = false;
|
||||
}
|
||||
|
||||
if (move_status) {
|
||||
if (move_status != s_last_move_status) {
|
||||
led_strip_set_pixel(led_strip, 0, 0, 255, 0);
|
||||
ESP_LOGI(TAG, "someone moves in the room");
|
||||
}
|
||||
|
||||
s_last_move_time = esp_log_timestamp();
|
||||
} else if (move_status != s_last_move_status) {
|
||||
ESP_LOGI(TAG, "No one moves in the room");
|
||||
} else if (esp_log_timestamp() - s_last_move_time > 3 * 1000) {
|
||||
if (someone_status) {
|
||||
led_strip_set_pixel(led_strip, 0, 255, 255, 255);
|
||||
} else {
|
||||
led_strip_set_pixel(led_strip, 0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
led_strip_refresh(led_strip);
|
||||
s_last_move_status = move_status;
|
||||
|
||||
/**
|
||||
* @brief Report the room status to the cloud every 10 seconds or when the room status changes
|
||||
*/
|
||||
if (!esp_rmaker_time_check()) {
|
||||
return;
|
||||
}
|
||||
|
||||
static bool s_report_someone_status = false;
|
||||
static bool s_report_move_status = false;
|
||||
static uint32_t s_report_move_count = 0;
|
||||
static uint32_t s_report_move_timestamp = 0;
|
||||
s_report_move_count = move_status ? s_report_move_count + 1 : s_report_move_count;
|
||||
|
||||
if (s_report_someone_status != someone_status && !someone_status) {
|
||||
esp_rmaker_param_t *someone_status_param = esp_rmaker_device_get_param_by_name(radar_device, RADAR_PARAM_SOMEONE_STATUS);
|
||||
esp_rmaker_param_update_and_report(someone_status_param, esp_rmaker_bool(someone_status));
|
||||
s_report_someone_status = someone_status;
|
||||
}
|
||||
|
||||
if (move_status != s_report_move_status
|
||||
/* Reduce the number of times to report data and reduce server pressure */
|
||||
|| (move_status && esp_log_timestamp() - s_report_move_timestamp > 10 * 1000)) {
|
||||
esp_rmaker_param_t *someone_status_param = esp_rmaker_device_get_param_by_name(radar_device, RADAR_PARAM_SOMEONE_STATUS);
|
||||
esp_rmaker_param_update(someone_status_param, esp_rmaker_bool(someone_status));
|
||||
esp_rmaker_param_t *move_status_param = esp_rmaker_device_get_param_by_name(radar_device, RADAR_PARAM_MOVE_STATUS);
|
||||
esp_rmaker_param_update(move_status_param, esp_rmaker_bool(move_status | (s_report_move_count > 0)));
|
||||
esp_rmaker_param_t *move_count_param = esp_rmaker_device_get_param_by_name(radar_device, RADAR_PARAM_MOVE_COUNT);
|
||||
esp_rmaker_param_update_and_report(move_count_param, esp_rmaker_int(s_report_move_count));
|
||||
|
||||
if (!s_report_move_status || !s_report_move_count) {
|
||||
s_report_move_status = move_status;
|
||||
}
|
||||
|
||||
s_report_move_count = 0;
|
||||
s_report_move_timestamp = esp_log_timestamp();
|
||||
}
|
||||
}
|
||||
|
||||
static esp_err_t radar_start()
|
||||
{
|
||||
esp_radar_config_t radar_config = ESP_RADAR_CONFIG_DEFAULT();
|
||||
#if CONFIG_IDF_TARGET_ESP32C5 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32C61
|
||||
// radar_config.csi_config.acquire_csi_lltf = true;
|
||||
// radar_config.csi_config.htltf_en = true;
|
||||
#else
|
||||
// radar_config.csi_config.lltf_en = true;
|
||||
// radar_config.csi_config.htltf_en = true;
|
||||
|
||||
#endif
|
||||
radar_config.dec_config.wifi_radar_cb = radar_cb;
|
||||
|
||||
wifi_ap_record_t ap_info = {0x0};
|
||||
esp_wifi_sta_get_ap_info(&ap_info);
|
||||
memcpy(radar_config.csi_config.filter_mac, ap_info.bssid, sizeof(ap_info.bssid));
|
||||
ESP_ERROR_CHECK(esp_radar_csi_init(&radar_config.csi_config));
|
||||
ESP_ERROR_CHECK(esp_radar_dec_init(&radar_config.dec_config));
|
||||
|
||||
esp_radar_start();
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void auto_calibrate_timercb(TimerHandle_t timer)
|
||||
{
|
||||
g_auto_calibrate_timerleft -= AUTO_CALIBRATE_RAPORT_INTERVAL;
|
||||
|
||||
if (g_auto_calibrate_timerleft < AUTO_CALIBRATE_RAPORT_INTERVAL) {
|
||||
g_auto_calibrate_timerleft = g_detect_config.threshold_calibrate_timeout;
|
||||
g_detect_config.threshold_calibrate = false;
|
||||
xTimerStop(g_auto_calibrate_timerhandle, portMAX_DELAY);
|
||||
|
||||
esp_radar_train_stop(&g_someone_threshold, &g_detect_config.move_threshold);
|
||||
esp_rmaker_param_t *move_threshold_param = esp_rmaker_device_get_param_by_name(radar_device, RADAR_PARAM_MOVE_THRESHOLD);
|
||||
esp_rmaker_param_update(move_threshold_param, esp_rmaker_float(g_detect_config.move_threshold));
|
||||
|
||||
nvs_set_blob(g_nvs_handle, "detect_config", &g_detect_config, sizeof(radar_detect_config_t));
|
||||
nvs_commit(g_nvs_handle);
|
||||
}
|
||||
|
||||
esp_rmaker_param_t *param_threshold_calibrate = esp_rmaker_device_get_param_by_name(radar_device, RADAR_PARAM_THRESHOLD_CALIBRATE);
|
||||
esp_rmaker_param_update(param_threshold_calibrate, esp_rmaker_bool(g_detect_config.threshold_calibrate));
|
||||
esp_rmaker_param_t *param_threshold_calibrate_timeout = esp_rmaker_device_get_param_by_name(radar_device, RADAR_PARAM_THRESHOLD_CALIBRATE_TIMEOUT);
|
||||
esp_rmaker_param_update_and_report(param_threshold_calibrate_timeout, esp_rmaker_int(g_auto_calibrate_timerleft));
|
||||
}
|
||||
|
||||
/* Callback to handle commands received from the RainMaker cloud */
|
||||
static esp_err_t write_cb(const esp_rmaker_device_t *device, const esp_rmaker_param_t *param,
|
||||
const esp_rmaker_param_val_t val, void *priv_data, esp_rmaker_write_ctx_t *ctx)
|
||||
{
|
||||
const char *param_name = esp_rmaker_param_get_name(param);
|
||||
|
||||
if (strcmp(param_name, RADAR_PARAM_SOMEONE_TIMEOUT) == 0) {
|
||||
g_detect_config.someone_timeout = val.val.i;
|
||||
} else if (strcmp(param_name, RADAR_PARAM_MOVE_THRESHOLD) == 0) {
|
||||
g_detect_config.move_threshold = val.val.f;
|
||||
} else if (strcmp(param_name, RADAR_PARAM_FILTER_WINDOW) == 0) {
|
||||
g_detect_config.filter_window = val.val.i;
|
||||
} else if (strcmp(param_name, RADAR_PARAM_FILTER_COUNT) == 0) {
|
||||
g_detect_config.filter_count = val.val.i;
|
||||
} else if (strcmp(param_name, RADAR_PARAM_THRESHOLD_CALIBRATE) == 0) {
|
||||
g_detect_config.threshold_calibrate = val.val.b;
|
||||
|
||||
if (!g_auto_calibrate_timerhandle) {
|
||||
g_auto_calibrate_timerhandle = xTimerCreate("auto_calibrate", pdMS_TO_TICKS(AUTO_CALIBRATE_RAPORT_INTERVAL * 1000),
|
||||
true, NULL, auto_calibrate_timercb);
|
||||
}
|
||||
|
||||
if (g_detect_config.threshold_calibrate) {
|
||||
g_auto_calibrate_timerleft = g_detect_config.threshold_calibrate_timeout;
|
||||
xTimerStart(g_auto_calibrate_timerhandle, portMAX_DELAY);
|
||||
esp_radar_train_start();
|
||||
} else {
|
||||
g_auto_calibrate_timerleft = 0;
|
||||
auto_calibrate_timercb(NULL);
|
||||
}
|
||||
} else if (strcmp(param_name, RADAR_PARAM_THRESHOLD_CALIBRATE_TIMEOUT) == 0) {
|
||||
g_detect_config.threshold_calibrate_timeout = val.val.i;
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Unhandled parameter '%s'", param_name);
|
||||
/* Silently ignoring invalid params */
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_rmaker_param_update_and_report(param, val);
|
||||
nvs_set_blob(g_nvs_handle, "detect_config", &g_detect_config, sizeof(radar_detect_config_t));
|
||||
nvs_commit(g_nvs_handle);
|
||||
return ESP_OK;
|
||||
}
|
||||
esp_err_t ws2812_led_init(void)
|
||||
{
|
||||
led_strip_config_t strip_config = {
|
||||
.strip_gpio_num = WS2812_GPIO,
|
||||
.max_leds = 1,
|
||||
};
|
||||
|
||||
led_strip_rmt_config_t rmt_config = {
|
||||
.clk_src = RMT_CLK_SRC_DEFAULT, // different clock source can lead to different power consumption
|
||||
.resolution_hz = 10 * 1000 * 1000, // RMT counter clock frequency: 10MHz
|
||||
.flags = {
|
||||
.with_dma = false, // DMA feature is available on chips like ESP32-S3/P4
|
||||
}
|
||||
};
|
||||
ESP_ERROR_CHECK(led_strip_new_rmt_device(&strip_config, &rmt_config, &led_strip));
|
||||
/* Set all LED off to clear all pixels */
|
||||
led_strip_clear(led_strip);
|
||||
return ESP_OK;
|
||||
}
|
||||
void app_main()
|
||||
{
|
||||
/* Initialize Application specific hardware drivers and set initial state */
|
||||
ws2812_led_init();
|
||||
button_handle_t btn_handle = iot_button_create(BUTTON_GPIO, BUTTON_ACTIVE_LOW);
|
||||
app_reset_button_register(btn_handle, BUTTON_WIFI_RESET_TIMEOUT, BUTTON_FACTORY_RESET_TIMEOUT);
|
||||
|
||||
/* Initialize NVS. */
|
||||
esp_err_t err = nvs_flash_init();
|
||||
if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
||||
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||
err = nvs_flash_init();
|
||||
}
|
||||
ESP_ERROR_CHECK(err);
|
||||
nvs_open("wifi_radar", NVS_READWRITE, &g_nvs_handle);
|
||||
size_t detect_config_size = sizeof(radar_detect_config_t);
|
||||
nvs_get_blob(g_nvs_handle, "detect_config", &g_detect_config, &detect_config_size);
|
||||
|
||||
/* Reduced output log */
|
||||
// esp_log_level_set("esp_radar", ESP_LOG_WARN);
|
||||
esp_log_level_set("RADAR_DADA", ESP_LOG_WARN);
|
||||
|
||||
/* Initialize Wi-Fi. Note that, this should be called before esp_rmaker_node_init() */
|
||||
app_wifi_init();
|
||||
|
||||
/* Initialize the ESP RainMaker Agent */
|
||||
esp_rmaker_config_t rainmaker_cfg = {
|
||||
.enable_time_sync = true,
|
||||
};
|
||||
esp_rmaker_node_t *node = esp_rmaker_node_init(&rainmaker_cfg, "ESP Wi-Fi CSI Device", "Wi-Fi Radar");
|
||||
if (!node) {
|
||||
ESP_LOGE(TAG, "Could not initialise node. Aborting!!!");
|
||||
vTaskDelay(pdMS_TO_TICKS(5000));
|
||||
abort();
|
||||
}
|
||||
|
||||
/* Create a device and add the relevant parameters to it */
|
||||
radar_device = esp_rmaker_device_create("Sensor Light", ESP_RMAKER_DEVICE_LIGHTBULB, NULL);
|
||||
ESP_ERROR_CHECK(esp_rmaker_device_add_cb(radar_device, write_cb, NULL));
|
||||
|
||||
typedef struct {
|
||||
const char *param_name;
|
||||
uint8_t properties;
|
||||
const char *ui_type;
|
||||
esp_rmaker_param_val_t val;
|
||||
esp_rmaker_param_val_t min;
|
||||
esp_rmaker_param_val_t max;
|
||||
esp_rmaker_param_val_t step;
|
||||
} radar_param_t;
|
||||
esp_rmaker_param_val_t invalid_val = {.type = RMAKER_VAL_TYPE_INVALID};
|
||||
radar_param_t radar_param_list[] = {
|
||||
{RADAR_PARAM_THRESHOLD_CALIBRATE, PROP_FLAG_READ | PROP_FLAG_WRITE, ESP_RMAKER_UI_TOGGLE, esp_rmaker_bool(g_detect_config.threshold_calibrate), invalid_val, invalid_val, invalid_val},
|
||||
{RADAR_PARAM_THRESHOLD_CALIBRATE_TIMEOUT, PROP_FLAG_READ | PROP_FLAG_WRITE, ESP_RMAKER_UI_TEXT, esp_rmaker_int(g_detect_config.threshold_calibrate_timeout), esp_rmaker_int(10), esp_rmaker_int(3600), esp_rmaker_int(10)},
|
||||
{RADAR_PARAM_MOVE_THRESHOLD, PROP_FLAG_READ | PROP_FLAG_WRITE, ESP_RMAKER_UI_TEXT, esp_rmaker_float(g_detect_config.move_threshold), esp_rmaker_float(0.01), esp_rmaker_float(0.1), esp_rmaker_float(0.01)},
|
||||
{RADAR_PARAM_MOVE_STATUS, PROP_FLAG_READ, ESP_RMAKER_UI_TEXT, esp_rmaker_bool(false), invalid_val, invalid_val, invalid_val},
|
||||
{RADAR_PARAM_MOVE_COUNT, PROP_FLAG_READ | PROP_FLAG_TIME_SERIES, ESP_RMAKER_UI_TEXT, esp_rmaker_int(0), esp_rmaker_int(0), esp_rmaker_int(100), esp_rmaker_int(1)},
|
||||
{RADAR_PARAM_SOMEONE_STATUS, PROP_FLAG_READ, ESP_RMAKER_UI_TEXT, esp_rmaker_bool(false), invalid_val, invalid_val, invalid_val},
|
||||
{RADAR_PARAM_SOMEONE_TIMEOUT, PROP_FLAG_READ | PROP_FLAG_WRITE, ESP_RMAKER_UI_TEXT, esp_rmaker_int(g_detect_config.someone_timeout), esp_rmaker_int(10), esp_rmaker_int(3600), esp_rmaker_int(10)},
|
||||
{RADAR_PARAM_FILTER_WINDOW, PROP_FLAG_READ | PROP_FLAG_WRITE, ESP_RMAKER_UI_TEXT, esp_rmaker_int(g_detect_config.filter_window), esp_rmaker_int(1), esp_rmaker_int(16), esp_rmaker_int(1)},
|
||||
{RADAR_PARAM_FILTER_COUNT, PROP_FLAG_READ | PROP_FLAG_WRITE, ESP_RMAKER_UI_TEXT, esp_rmaker_int(g_detect_config.filter_count), esp_rmaker_int(1), esp_rmaker_int(16), esp_rmaker_int(1)},
|
||||
};
|
||||
|
||||
for (int i = 0; i < sizeof(radar_param_list) / sizeof(radar_param_list[0]); ++i) {
|
||||
char radar_param_type[64] = "esp.param.";
|
||||
strcat(radar_param_type, radar_param_list[i].param_name);
|
||||
esp_rmaker_param_t *param = esp_rmaker_param_create(radar_param_list[i].param_name, radar_param_type,
|
||||
radar_param_list[i].val, radar_param_list[i].properties);
|
||||
|
||||
if (radar_param_list[i].ui_type) {
|
||||
esp_rmaker_param_add_ui_type(param, radar_param_list[i].ui_type);
|
||||
}
|
||||
|
||||
if (radar_param_list[i].min.type != RMAKER_VAL_TYPE_INVALID) {
|
||||
esp_rmaker_param_add_bounds(param, radar_param_list[i].min, radar_param_list[i].max, radar_param_list[i].step);
|
||||
}
|
||||
|
||||
ESP_ERROR_CHECK(esp_rmaker_device_add_param(radar_device, param));
|
||||
}
|
||||
|
||||
esp_rmaker_param_t *move_count_param = esp_rmaker_device_get_param_by_name(radar_device, RADAR_PARAM_MOVE_COUNT);
|
||||
esp_rmaker_device_assign_primary_param(radar_device, move_count_param);
|
||||
ESP_ERROR_CHECK(esp_rmaker_node_add_device(node, radar_device));
|
||||
|
||||
/* Enable OTA */
|
||||
ESP_ERROR_CHECK(esp_rmaker_ota_enable_default());
|
||||
|
||||
/* Enable timezone service which will be require for setting appropriate timezone
|
||||
* from the phone apps for scheduling to work correctly.
|
||||
* For more information on the various ways of setting timezone, please check
|
||||
* https://rainmaker.espressif.com/docs/time-service.html.
|
||||
*/
|
||||
esp_rmaker_timezone_service_enable();
|
||||
|
||||
/* Enable scheduling. */
|
||||
esp_rmaker_schedule_enable();
|
||||
|
||||
/* Enable Scenes */
|
||||
esp_rmaker_scenes_enable();
|
||||
|
||||
/* Start the ESP RainMaker Agent */
|
||||
esp_rmaker_start();
|
||||
|
||||
/* Start the Wi-Fi./
|
||||
* If the node is provisioned, it will start connection attempts,
|
||||
* else, it will start Wi-Fi provisioning. The function will return
|
||||
* after a connection has been successfully established
|
||||
*/
|
||||
err = app_wifi_start(POP_TYPE_NONE);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Could not start Wifi. Aborting!!!");
|
||||
vTaskDelay(pdMS_TO_TICKS(5000));
|
||||
abort();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable Wi-Fi Radar Detection
|
||||
*/
|
||||
radar_start();
|
||||
ping_router_start(RADAR_PING_DATA_INTERVAL);
|
||||
}
|
||||
32
esp-radar/connect_rainmaker/main/idf_component.yml
Normal file
32
esp-radar/connect_rainmaker/main/idf_component.yml
Normal file
@@ -0,0 +1,32 @@
|
||||
## IDF Component Manager Manifest File
|
||||
dependencies:
|
||||
idf: '>=4.4.1'
|
||||
|
||||
esp-radar:">=0.3.0"
|
||||
|
||||
espressif/rmaker_common: 1.4.*
|
||||
espressif/json_generator: ^1
|
||||
espressif/json_parser: =1.0.0
|
||||
espressif/esp_rainmaker:
|
||||
path: components/esp_rainmaker
|
||||
git: https://github.com/espressif/esp-rainmaker.git
|
||||
version: ff0dd329020a52ae8cf2fb4f6800d9f8e9cc9eeb
|
||||
espressif/led_strip: "^2.5.3"
|
||||
espressif/qrcode:
|
||||
path: components/qrcode
|
||||
git: https://github.com/espressif/esp-rainmaker.git
|
||||
version: ff0dd329020a52ae8cf2fb4f6800d9f8e9cc9eeb
|
||||
espressif/gpio_button:
|
||||
path: components/gpio_button
|
||||
git: https://github.com/espressif/esp-rainmaker.git
|
||||
version: ff0dd329020a52ae8cf2fb4f6800d9f8e9cc9eeb
|
||||
espressif/app_wifi:
|
||||
path: examples/common/app_wifi
|
||||
git: https://github.com/espressif/esp-rainmaker.git
|
||||
version: ff0dd329020a52ae8cf2fb4f6800d9f8e9cc9eeb
|
||||
espressif/app_reset:
|
||||
path: examples/common/app_reset
|
||||
git: https://github.com/espressif/esp-rainmaker.git
|
||||
version: ff0dd329020a52ae8cf2fb4f6800d9f8e9cc9eeb
|
||||
espressif/esp_schedule:
|
||||
version: ^1.2.0
|
||||
8
esp-radar/connect_rainmaker/partitions.csv
Normal file
8
esp-radar/connect_rainmaker/partitions.csv
Normal file
@@ -0,0 +1,8 @@
|
||||
# Note: Firmware partition offset needs to be 64K aligned, initial 36K (9 sectors) are reserved for bootloader and partition table
|
||||
# Name, Type, SubType, Offset, Size, Flags
|
||||
nvs, data, nvs, 0xd000, 32K,
|
||||
fctry, data, nvs, 0x15000, 16K,
|
||||
log_status, data, nvs, 0x19000, 16K,
|
||||
otadata, data, ota, 0x1d000, 8K,
|
||||
phy_init, data, phy, 0x1f000, 4K,
|
||||
ota_0, app, ota_0, 0x20000, 1832K,
|
||||
|
19
esp-radar/connect_rainmaker/sdkconfig.defaults
Normal file
19
esp-radar/connect_rainmaker/sdkconfig.defaults
Normal file
@@ -0,0 +1,19 @@
|
||||
CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE=y
|
||||
CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
|
||||
CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
|
||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||
CONFIG_PARTITION_TABLE_OFFSET=0x9000
|
||||
CONFIG_ESP_RMAKER_USER_ID_CHECK=y
|
||||
CONFIG_ESP_RMAKER_LOCAL_CTRL_ENABLE=y
|
||||
CONFIG_BT_NIMBLE_ENABLED=y
|
||||
CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y
|
||||
CONFIG_ESP_TASK_WDT_TIMEOUT_S=30
|
||||
CONFIG_ESP_WIFI_CSI_ENABLED=y
|
||||
# CONFIG_ESP_WIFI_AMPDU_TX_ENABLED is not set
|
||||
# CONFIG_ESP_WIFI_AMPDU_RX_ENABLED is not set
|
||||
# CONFIG_ESP_WIFI_IRAM_OPT is not set
|
||||
CONFIG_FREERTOS_HZ=1000
|
||||
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=3120
|
||||
CONFIG_MBEDTLS_DYNAMIC_BUFFER=y
|
||||
CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA=y
|
||||
CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN=y
|
||||
13
esp-radar/console_test/CMakeLists.txt
Normal file
13
esp-radar/console_test/CMakeLists.txt
Normal file
@@ -0,0 +1,13 @@
|
||||
# The following lines of boilerplate have to be in your project's CMakeLists
|
||||
# in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
add_compile_options(-fdiagnostics-color=always)
|
||||
|
||||
set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/system/console/advanced/components)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
string(REGEX REPLACE ".*/\(.*\)" "\\1" CURDIR ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
project(${CURDIR})
|
||||
|
||||
git_describe(PROJECT_VERSION ${COMPONENT_DIR})
|
||||
message("Project commit: " ${PROJECT_VERSION})
|
||||
178
esp-radar/console_test/README.md
Normal file
178
esp-radar/console_test/README.md
Normal file
@@ -0,0 +1,178 @@
|
||||
| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-S2 | ESP32-S3 |
|
||||
| ----------------- | ----- | -------- | -------- | -------- | --------- | -------- | -------- |
|
||||
|
||||
# esp-csi console_test [[中文]](./README_cn.md)
|
||||
----------
|
||||
## 1 Introduction
|
||||
This example provides a test platform for Wi-Fi CSI, which includes functions such as data display, data acquisition and data analysis, which can help you quickly understand Wi-Fi CSI.
|
||||
+ **Display**:you can quickly understand the impact of different antennas, human movement and equipment placement on Wi-Fi signals by viewing the real-time data such as Wi-Fi RF noise bottom, CSI, RSSI and noise floor of RF.
|
||||
+ **Acquisition**:All collected Wi-Fi CSIS will be stored in files. You can also mark the data for different motor behaviors for later neural network and machine learning.
|
||||
+ **Analysis**:It can realize the detection of human movement and whether there are people in the room, and help you quickly the application scenario of Wi-Fi CSI.
|
||||
## 2 Equipment preparation
|
||||
### 2.1 Equipment
|
||||

|
||||
This example provides two working modes of `ESP32 DevKitC development board` and `router` as Wi-Fi CSI contracting equipment. Using `ESP32 DevKitC development board` as contracting equipment has better adjustment effect on contracting rate, RF size and channel. In both modes, `ESP32 DevKitC development board` is used as the receiving device for Wi-Fi CSI.
|
||||
|
||||
### 2.2 Compiler Environment
|
||||
The esp-idf version of the current project is [ESP-IDF Release v5.0.2](https://github.com/espressif/esp-idf/releases/tag/v5.0.2)
|
||||
```bash
|
||||
cd esp-idf
|
||||
git checkout v5.0.2
|
||||
git submodule update --init --recursive
|
||||
./install.sh
|
||||
. ./export.sh
|
||||
```
|
||||
> Note: Since esp-idf v5.0.0 or above supports destination address filtering, the effect will be better, so it is recommended to use v5.0.0 or above
|
||||
|
||||
## 3 Starting program
|
||||
### 3.1 Send Wi-Fi CSI
|
||||
+ **Use `ESP32 DevKitC` to send CSI**:Burn project `csi_send` to `ESP32 DevKitC development board`
|
||||
|
||||
```bash
|
||||
cd esp-csi/examples/get-started/csi_send
|
||||
idf.py set-target esp32s3
|
||||
idf.py flash -b 921600 -p /dev/ttyUSB0 monitor
|
||||
```
|
||||
+ **Use router to send CSI**:The router is not connected to other intelligent devices to avoid network congestion affecting the test effect.
|
||||
|
||||
### 3.2 Receive Wi-Fi CSI
|
||||
+ Burn project `console_test` to another `ESP32 DevKitC development board`
|
||||
```bash
|
||||
cd esp-csi/examples/console_test
|
||||
idf.py set-target esp32s3
|
||||
idf.py flash -b 921600 -p /dev/ttyUSB1
|
||||
```
|
||||
|
||||
### 3.3 Start up `esp-csi-tool`. Open the CSI visualization interface
|
||||
+ Run `esp_csi_tool.py` in `csi_recv` for data analysis. Please close `idf.py monitor` before running. Please use UART port instead of USB Serial/JTAG port.
|
||||
```bash
|
||||
cd esp-csi/examples/console_test/tools
|
||||
# Install python related dependencies
|
||||
pip install -r requirements.txt
|
||||
# Graphical display
|
||||
python esp_csi_tool.py -p /dev/ttyUSB1
|
||||
```
|
||||
+ After running successfully, the following CSI data visualization interface is opened. The left side of the interface is the data display interface `Raw data`, and the right side is the data model interface `Raw model`:
|
||||
|
||||
## 4 Interface introduction
|
||||
The real-time visualization interface consists of two parts: the `Raw data` and the `Radar model`. `Raw data` displays the original CSI sub-carrier data, and `Radar model` uses algorithms to analyze the CSI data. As a result, it can be used for detection of someone/noneone, move/static, by selecting the `Raw data` and `Radar model` buttons in the upper right corner, you can choose to display the two interfaces separately.
|
||||
|
||||
### 4.1 Router connection window
|
||||
The top left is the configuration router connection information window. Use the device to connect to the router and receive the CSI between the router and the device.
|
||||
|
||||

|
||||
|
||||
+ **SSID**:router account
|
||||
+ **password**:router password
|
||||
+ **auto connect**:If checked, the next time you turn it on, it will automatically connect to the last connected router.
|
||||
+ **connect / disconnect**:connect/disconnect button
|
||||
+ **custom**:You can send more control commands such as: restart, version acquisition, or enter custom commands on the device side
|
||||
|
||||
### 4.2 CSI data waveform display window
|
||||
This window can display the waveform of some channel CSI data in real time. If `wave filtering` is checked, the filtered waveform will be displayed.
|
||||

|
||||
|
||||
### 4.3 RSSI waveform display window
|
||||
This window displays the RSSI waveform information, which can be used to compare with the CSI waveform to observe the changes of RSSI when the personnel in the room are in different states.
|
||||

|
||||
|
||||
### 4.4 log display window
|
||||
This window displays system logs such as time, memory, etc.
|
||||

|
||||
|
||||
### 4.5 Wi-Fi channel data display window
|
||||
This window displays Wi-Fi channel status information.
|
||||

|
||||
|
||||
### 4.6 Room status display window
|
||||
This window is used to calibrate the room status threshold and display room status ( someone/noneone, move/static ).
|
||||
|
||||
+ **delay**:start calibration delay time, no one is required in the room during calibration, and people can leave the room within the delay time after starting calibration.
|
||||
+ **duration**:calibration process duration.
|
||||
+ **add**:if checked, the recalibrated threshold will be accumulated based on the current threshold.
|
||||
+ **start**:start calibration button.
|
||||
+ **wander(someone) threshold**:the threshold for judging room presence/absence will be set automatically after calibration, or can be set manually by the user.
|
||||
+ **jitter(move) threshold**:the threshold for judging the move/static of people will be set automatically after calibration, or it can be set manually by the user.
|
||||
+ **config**:after the user manually sets the threshold, click the configure button.
|
||||
+ **display table**:if checked, the room status and people status information table will be displayed on the right side of the waveform box. The specific parameters in the table are as follows.
|
||||
|
||||
|status|threshold|value|max|min|mean|std|
|
||||
|---|---|---|---|---|---|---|
|
||||
|room/people status|Judgment threshold|real-time value|maximum value|minimum value|average value|standard deviation|
|
||||
|
||||
### 4.7 People movement data display window
|
||||
This window displays the specific data of indoor people's movement, the bar graph on the left shows the number of people's movement in real time, and the table on the right records the specific movement time.
|
||||

|
||||
|
||||
+ **mode**:observation mode, `minute, hour, day` three modes are to record the number of people's movements per minute, hour, and day.
|
||||
+ **time**:observation time, the default current time, you can manually set the time to start the observation.
|
||||
+ **auto update**:if checked, the bar graph of the number of people's movements will be automatically updated and displayed in real time.
|
||||
+ **update**:after clicking, the bar graph of the number of people's movements will be manually updated and displayed.
|
||||
|
||||
The meaning of each parameter in the table is as follows:
|
||||
|room|human|spend_time|start_time|stop_time|
|
||||
|---|---|---|---|---|
|
||||
|room status|people status|spend time of movement|start time of movement|stop time of movement|
|
||||
|
||||
### 4.8 Action collection window
|
||||
This window is used to collect CSI data when people perform different actions. The collected data will be stored under the path of `esp-csi/examples/console_test/tools/data`, and the collected data can be used for machine learning or neural network.
|
||||

|
||||
|
||||
+ **target**:Select the motor behaviors to collect
|
||||
+ **delay**:Select the delay time of collection, which is how long to wait after clicking the `start` button
|
||||
+ **duration**:The duration of collecting an action
|
||||
+ **number**:Collection times
|
||||
+ **clean**:Click to clear all collected data
|
||||
+ **start**:start collecting button
|
||||
|
||||
## 5 Operating procedures
|
||||
Here, taking connecting the router as an example, the operation flow of the visualization system interface is introduced.
|
||||
### 5.1 connect router
|
||||
+ Enter the router account and password in turn in the router connection window
|
||||
+ (option)check `auto connect`
|
||||
+ Click `connect`
|
||||
|
||||
After the connection is successful, you will see the router status information in the "log print window", and the "CSI data waveform display window" will display the CSI data waveform.
|
||||
|
||||
### 5.2 Calibration threshold
|
||||
The purpose of calibration is to let the device know the CSI information when there is no one in the room, and to obtain the threshold of personnel movement. If the current version does not calibrate, only personnel movement detection can be performed. The longer the calibration time, the lower the probability of false touches.
|
||||

|
||||
|
||||
+ Set the delay time of `delay`, here is 10 seconds for example (i.e. 00:00:10), so that people can leave the room.
|
||||
+ Set the duration of `duration` calibration, here is 10 seconds as an example.
|
||||
+ Click `start` and select `yes`, the person leaves the room within 10 seconds (`delay` time), ensure that there is no one in the room within 10 seconds during the calibration period (`duration` calibration duration), and return to the room after the calibration.
|
||||
+ ( option ) to manually adjust the room status threshold and the person status threshold based on the calibration results.
|
||||
|
||||
### 5.3 Observe room status and people status
|
||||
|
||||
After the calibration is completed, the room status will be displayed in the room status display window, and it will be judged that there is noneone static, someone moves, and someone static three status.
|
||||
|
||||
+ In `filter outliers`, set how many times the threshold is reached in a row to determine the room/people state, so as to filter outliers.
|
||||
+ Click `config` to configure.
|
||||
+ ( option ) In the room status waveform window, click the horizontal line in front of `wander` to hide its waveform, which is convenient for observing other waveforms. Similarly, other waveforms can also be hidden by the following method.
|
||||
+ ( option ) Check `display table` to view the indoor status and people status information table.
|
||||
|
||||
### 5.4 Observer movement times and the time
|
||||
In these observation windows, the number of people's movements per minute will be displayed in a histogram according to our settings. The time information of each movement is recorded in the table on the right.
|
||||

|
||||
|
||||
+ In the `mode` of the people's movement data display window, select the observation mode to view the movement of the people in the room in one minute, one hour or one day. Here, choose `minute` as an example.
|
||||
+ ( option ) Set the time to start the observation in `time`, the default is the current time start.
|
||||
+ Check `auto update` to automatically update the test results, if not checked, each time you click `update`, the test results will be updated once.
|
||||
|
||||
### 5.5 Collect CSI data for a specific action
|
||||

|
||||
+ ( option ) Clear previous acquisition data records in `clean` in the motion acquisition window.
|
||||
+ In `target`, select the action to be collected, here select `move` as an example.
|
||||
+ In `delay`, set the delayed acquisition time after clicking to start, here is an example of setting a delay of 5 seconds.
|
||||
+ In `duration`, set the duration of collecting an action in, here we choose 500 ms as an example.
|
||||
+ In `number`, set the number of times to be collected, here is 1 collection as an example.
|
||||
+ Click `start`, the system will start collecting data after the delay time, and the personnel will complete the corresponding action within the set time.
|
||||
|
||||
After the collection is over, it will stop automatically. We can see the data we collected under the path of `esp-csi/examples/esp-radar/console_test/tools/data`.
|
||||

|
||||
|
||||
### 5.6 Window zoom in and out
|
||||

|
||||
+ By selecting `Raw data` and `Radar model` in the upper right corner of the interface, the `Raw data` interface and `Radar model` interface can be displayed separately.
|
||||
+ Select the critical line between different windows with the mouse, and drag and drop to zoom in/out of each window.
|
||||
180
esp-radar/console_test/README_cn.md
Normal file
180
esp-radar/console_test/README_cn.md
Normal file
@@ -0,0 +1,180 @@
|
||||
| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-S2 | ESP32-S3 |
|
||||
| ----------------- | ----- | -------- | -------- | -------- | --------- | -------- | -------- |
|
||||
|
||||
# esp-csi console_test [[English]](./README.md)
|
||||
----------
|
||||
## 1 简介
|
||||
console_test 是一款 Wi-Fi CSI 的测试平台,它包含了对 Wi-Fi CSI 的数据采集、数据显示、数据分析等功能,帮助我们更好的了解和应用 Wi-Fi CSI
|
||||
+ **显示**:通过查看 Wi-Fi 射频底噪、CSI、RSSI 及射频底噪等实时数据,可以快速了解不同天线、人体运动和设备摆放对 Wi-Fi 信号的影响。
|
||||
+ **采集**:所有采集到的 Wi-Fi CSI 将存储在文件中。您还可以采集不同运动行为的数据,以供以后的神经网络和机器学习使用
|
||||
+ **分析**:可实现检测人体是否运动及房间内是否有人,帮助您快速了解 Wi-Fi CSI 的应用场景
|
||||
|
||||
## 2 环境准备
|
||||
### 2.1 设备
|
||||

|
||||
本例提供了 `ESP32 DevKitC 开发板` 和 `路由器` 两种设备模式作为 Wi-Fi CSI 发送设备。 其中使用 `ESP32 DevKitC 开发板` 作为发送设备,对发送频率、射频大小、信道的调整效果更好。两种模式下都用 `ESP32 DevKitC 开发板` 作为 Wi-Fi CSI 的接收设备。
|
||||
|
||||
### 2.2 编译环境
|
||||
使用的 esp-idf 版本为 [ESP-IDF Release v5.0.2](https://github.com/espressif/esp-idf/releases/tag/v5.0.2)
|
||||
```bash
|
||||
cd esp-idf
|
||||
git checkout v5.0.2
|
||||
git submodule update --init --recursive
|
||||
./install.sh
|
||||
. ./export.sh
|
||||
```
|
||||
> 注: 由于 esp-idf v5.0.0 以上的版本支持目的地址过滤,其效果会更好,因此建议使用 v5.0.0 以上的版本
|
||||
|
||||
## 3 程序启动
|
||||
### 3.1 发送 Wi-Fi CSI
|
||||
+ ** `ESP32 DevKitC 开发板` 发送 CSI**:烧录工程 `csi_send` 到 `ESP32 DevKitC 开发板` 中
|
||||
```bash
|
||||
cd esp-csi/examples/get-started/csi_send
|
||||
idf.py set-target esp32s3
|
||||
idf.py flash -b 921600 -p /dev/ttyUSB0 monitor
|
||||
```
|
||||
+ **路由器 发送 CSI**:此时路由器不连接其他智能设备,避免网络拥塞影响测试效果
|
||||
|
||||
### 3.2 接收 Wi-Fi CSI
|
||||
+ 烧录 `console_test` 到另一块 `ESP32 DevKitC 开发板` 开发板中
|
||||
```bash
|
||||
cd esp-csi/examples/console_test
|
||||
idf.py set-target esp32s3
|
||||
idf.py flash -b 921600 -p /dev/ttyUSB1
|
||||
```
|
||||
|
||||
### 3.3 启动 `esp-csi-tool` 工具,打开 CSI 实时可视化工具,请使用 UART 口而不是 USB Serial/JTAG 口
|
||||
+ 运行 `csi_recv` 中的 `esp_csi_tool.py` 进行数据分析,运行前请关闭 `idf.py` 监控
|
||||
```bash
|
||||
cd esp-csi/examples/console_test/tools
|
||||
# Install python related dependencies
|
||||
pip install -r requirements.txt
|
||||
# Graphical display
|
||||
python esp_csi_tool.py -p /dev/ttyUSB1
|
||||
```
|
||||
+ 运行成功后,打开如下 CSI 数据实时可视化界面,界面左侧为数据显示界面,右侧为数据模型界面:
|
||||

|
||||
|
||||
## 4 界面介绍
|
||||
实时可视化界面由数据显示界面 `Raw data` 和数据模型界面 `Radar model` 两部分组成,`Raw data` 显示原始的 CSI 各个子载波的数据,`Radar model` 是使用算法对 CSI 数据分析后的结果,可以用于有人/无人、运动/静止的检测,通过选择勾选右上角 `Raw data` 和 `Radar model` 按钮,可以选择单独显示两个界面
|
||||
|
||||
### 4.1 路由器连接窗口:
|
||||
左侧最上方为配置路由器连接信息窗口,使用设备连接到路由器上,接收路由器的与设备之间 CSI
|
||||
|
||||

|
||||
|
||||
+ **ssid**:路由器帐号
|
||||
+ **password**:路由器密码
|
||||
+ **auto connect**:如果勾选,下次打开时,将自动连接上次连接的路由器
|
||||
+ **connect / disconnect**:连接/断开按钮
|
||||
+ **custom**:可以发送更多的控制指令如:重启、版本获取,或者输入设备端自定义的命令
|
||||
|
||||
### 4.2 CSI 数据波形显示窗口
|
||||
此窗口可实时显示部分通道 CSI 数据的波形,如果勾选 `wave filtering`,显示的就是滤波后的波形
|
||||

|
||||
|
||||
### 4.3 RSSI 波形显示窗口
|
||||
此窗口显示 RSSI 波形信息,可用于与 CSI 波形比较,观测室内人员处于不同处态时 RSSI 变化情况
|
||||

|
||||
|
||||
### 4.4 log 显示窗口
|
||||
此窗口显示时间,内存等系统日志
|
||||

|
||||
|
||||
### 4.5 Wi-Fi 信道数据显示窗口
|
||||
此窗口显示 Wi-Fi 信道状态信息
|
||||

|
||||
|
||||
### 4.6 室内状态显示窗口
|
||||
此窗口用于校准室内状态阈值,和显示室内状态(有人/无人、运动/静止)
|
||||

|
||||
|
||||
+ **delay**:开始校准延迟时间,校准时要求室内无人,人员可在开始校准后,延迟时间内离开房间
|
||||
+ **duration**:校准过程持续时间
|
||||
+ **add**:如果勾选,再次校准后的阈值将在当前阈值基础上累加
|
||||
+ **start**:开始校准按钮
|
||||
+ **wander(someone) threshold**:判断室内有人/无人的阈值,将在校准后自动设置,也可以用户自己手动设置
|
||||
+ **jitter(move) threshold**:判断人员静止/运动的阈值,将在校准后自动设置,也可以用户自己手动设置
|
||||
+ **config**:用户手动设置阈值后,点击配置按钮
|
||||
+ **display table**:如果勾选,将在波形框右侧显示室内状态和人员状态信息表格,表格中具体参数如下
|
||||
|
||||
|status|threshold|value|max|min|mean|std|
|
||||
|---|---|---|---|---|---|---|
|
||||
|状态|阈值|实时值|最大值|最小值|平均值|标准差|
|
||||
|
||||
### 4.7 人员运动数据显示窗口
|
||||
此窗口显示室内人员运动的具体数据,左侧以柱状图实时显示人员运动次数,右侧表格记录具体运动时间
|
||||

|
||||
|
||||
+ **mode**:观测模式,`minute, hour, day` 三种模式分别为以每分钟、每小时、每天为单位记录人员运动的次数
|
||||
+ **time**:时间,默认当前时间,可手动设置开始观测的时间
|
||||
+ **auto update**:如果勾选,会自动实时更新显示人员运动次数柱状图
|
||||
+ **update**:点击后会手动更新显示人员运动次数柱状图
|
||||
|
||||
表格各参数意义如下:
|
||||
|room|human|spend_time|start_time|stop_time|
|
||||
|---|---|---|---|---|
|
||||
|房间状态|人员状态|运动时长|运动开始时间|运动结束时间|
|
||||
|
||||
### 4.8 动作采集窗口
|
||||
此窗口用于对人员做不同动作时的 CSI 数据进行采集,采集的数据将存储在 `esp-csi/examples/console_test/tools/data` 路径下,采集的数据可用于机器学习或神经网络
|
||||

|
||||
|
||||
+ **target**:选择要采集的动作
|
||||
+ **delay**:选择采集的延迟时间,即点击开始按钮后延迟多久开始采集
|
||||
+ **duration**:采集一次动作持续时长
|
||||
+ **number**:采集次数
|
||||
+ **clean**:点击后将清除所采集的所有数据
|
||||
+ **start**:开始采集按钮
|
||||
|
||||
## 5 操作流程
|
||||
这里以连接路由器为例,介绍了可视化系界面使用的操作流程
|
||||
### 5.1 连接路由器
|
||||
+ 在路由器连接窗口中依次输入路由器帐号和密码
|
||||
+ (可选)勾选 `auto connect`
|
||||
+ 点击 `connect`
|
||||
|
||||
连接成功后,将在 “log 打印窗口” 看到路由器状态信息,同时 “CSI 数据波形显示窗口” 显示 CSI 数据波形
|
||||
|
||||
### 5.2 校准阈值
|
||||
校准的目的是为让设备知晓房间无人状态下的 CSI 信息,并获取到人员移动的阈值,当前版本如果不校准仅能进行人员移动检测,校准时间越长误触的概率越低
|
||||

|
||||
|
||||
+ 设置 `delay` 延迟时间,这里设置 10 秒为例(即 00:00:10),以便人员可以离开房间
|
||||
+ 设置 `duration` 校准持续时长, 这里设置 10 秒为例
|
||||
+ 点击 `start` 后选择 `yes`,人员 10 秒(`delay` 延迟时间)内离开房间,确保校准期间 10 秒内(`duration` 校准持续时长)房间内无人,校准结束后返回房间
|
||||
+ (选择)可根据校准结果,手动调整房间状态阈值和人员状态阈值
|
||||
|
||||
### 5.3 观测房间状态和人员状态
|
||||
校准结束后,室内状态显示窗口中将显示室内状态,并判断房间内无人、有人静止、有人运动三种状态
|
||||

|
||||
|
||||
+ 在 `filter outliers` 中设置连续多少次内达到阈值多少次判定为有人/运动状态,以便过滤异常值
|
||||
+ 点击 `config` 进行配置
|
||||
+ (选择)在房间状态波形窗口,点击 `wander` 前的横线,可隐藏其波形,方便观测其他波形,同样其他波形也可以用次方法隐藏
|
||||
+ (选择)勾选 `display table` ,查看室内状态和人员状态信息表格
|
||||
|
||||
### 5.4 观测人员运动次数和时间
|
||||
在些观测窗口中,将会按照我们的设置以柱状图显示人员每分钟的运动数量在右侧表格中记录了每次运动时间信息。
|
||||

|
||||
|
||||
+ 在人员运动数据显示窗口的 `mode` 中,选择观测模式,可以查看某分钟、某小时或某天房间内人员的运行情况,这里选择 `minute` 为例
|
||||
+ (选择)在 `time` 中设置开始观测的时间,默认为当前时刻开始
|
||||
+ 勾选 `auto update` 自动更新检测结果,如果不勾选,每次点击 `update` 会更新一次检测结果
|
||||
|
||||
### 5.5 采集特定动作的 CSI 数据
|
||||

|
||||
+ (选择)在动作采集窗口的 `clean` 中清除以前的采集数据记录
|
||||
+ 在 `target` 中选择将要采集的动作,这里选择 `move` 为例
|
||||
+ 在 `delay` 中设置点击开始后的延迟采集时间,这里设置延迟 5 秒为例
|
||||
+ 在 `duration` 中设置采集一个动作持续的时间,这里选择 500 ms 为例
|
||||
+ 在 `number` 中设置要采集的次数,这里采集 1 次为例
|
||||
+ 点击 `start`,经过延迟时间后系统将开始采集数据,人员在设置时间内完成对应动作
|
||||
|
||||
采集结束后会自动停止,我们在 `esp-csi/examples/esp-radar/console_test/tools/data` 路径下可以看到我们采集的数据
|
||||

|
||||
|
||||
### 5.6 窗口放大与缩小
|
||||

|
||||
+ 通过选择勾选界面右上角 `Raw data` 与 `Radar model`,可单独显示 “数据显示界面” 和 “数据模型界面”
|
||||
+ 鼠标选中不同窗口间的临界线,通过拖拽可放大/缩小各窗口
|
||||
@@ -0,0 +1,5 @@
|
||||
idf_component_register(SRC_DIRS "src"
|
||||
INCLUDE_DIRS "include"
|
||||
REQUIRES "console" "mbedtls" "nvs_flash" "fatfs" "esp_wifi" "spi_flash")
|
||||
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
|
||||
31
esp-radar/console_test/components/commands/include/csi_commands.h
Executable file
31
esp-radar/console_test/components/commands/include/csi_commands.h
Executable file
@@ -0,0 +1,31 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "argtable3/argtable3.h"
|
||||
#include "esp_console.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /**< _cplusplus */
|
||||
|
||||
void cmd_register_ping(void);
|
||||
void cmd_register_system(void);
|
||||
void cmd_register_wifi_config(void);
|
||||
void cmd_register_wifi_scan(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /**< _cplusplus */
|
||||
225
esp-radar/console_test/components/commands/src/ping_cmd.c
Normal file
225
esp-radar/console_test/components/commands/src/ping_cmd.c
Normal file
@@ -0,0 +1,225 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "nvs_flash.h"
|
||||
#include "argtable3/argtable3.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_console.h"
|
||||
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/netdb.h"
|
||||
#include "lwip/sockets.h"
|
||||
|
||||
#include "ping/ping_sock.h"
|
||||
|
||||
static const char *TAG = "ping_cmd";
|
||||
|
||||
esp_ping_handle_t g_ping_handle = NULL;
|
||||
|
||||
static void ping_cmd_on_success(esp_ping_handle_t hdl, void *args)
|
||||
{
|
||||
uint8_t ttl;
|
||||
uint16_t seqno;
|
||||
uint32_t elapsed_time, recv_len;
|
||||
ip_addr_t target_addr;
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_SEQNO, &seqno, sizeof(seqno));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_TTL, &ttl, sizeof(ttl));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_IPADDR, &target_addr, sizeof(target_addr));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_SIZE, &recv_len, sizeof(recv_len));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_TIMEGAP, &elapsed_time, sizeof(elapsed_time));
|
||||
ESP_LOGD(TAG, "%d bytes from %s icmp_seq=%d ttl=%d time=%d ms",
|
||||
recv_len, ipaddr_ntoa((ip_addr_t *)&target_addr), seqno, ttl, elapsed_time);
|
||||
}
|
||||
|
||||
static void ping_cmd_on_timeout(esp_ping_handle_t hdl, void *args)
|
||||
{
|
||||
uint16_t seqno;
|
||||
ip_addr_t target_addr;
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_SEQNO, &seqno, sizeof(seqno));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_IPADDR, &target_addr, sizeof(target_addr));
|
||||
ESP_LOGW(TAG, "From %s icmp_seq=%d timeout", ipaddr_ntoa((ip_addr_t *)&target_addr), seqno);
|
||||
}
|
||||
|
||||
static void ping_cmd_on_end(esp_ping_handle_t hdl, void *args)
|
||||
{
|
||||
ip_addr_t target_addr;
|
||||
uint32_t transmitted;
|
||||
uint32_t received;
|
||||
uint32_t total_time_ms;
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_REQUEST, &transmitted, sizeof(transmitted));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_REPLY, &received, sizeof(received));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_IPADDR, &target_addr, sizeof(target_addr));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_DURATION, &total_time_ms, sizeof(total_time_ms));
|
||||
uint32_t loss = (uint32_t)((1 - ((float)received) / transmitted) * 100);
|
||||
|
||||
if (IP_IS_V4(&target_addr)) {
|
||||
ESP_LOGI(TAG, "\n--- %s ping statistics ---", inet_ntoa(*ip_2_ip4(&target_addr)));
|
||||
} else {
|
||||
ESP_LOGI(TAG, "\n--- %s ping statistics ---", inet6_ntoa(*ip_2_ip6(&target_addr)));
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "%d packets transmitted, %d received, %d%% packet loss, time %dms",
|
||||
transmitted, received, loss, total_time_ms);
|
||||
// delete the ping sessions, so that we clean up all resources and can create a new ping session
|
||||
// we don't have to call delete function in the callback, instead we can call delete function from other tasks
|
||||
esp_ping_delete_session(hdl);
|
||||
g_ping_handle = NULL;
|
||||
}
|
||||
|
||||
static struct {
|
||||
struct arg_int *timeout;
|
||||
struct arg_int *interval;
|
||||
struct arg_int *data_size;
|
||||
struct arg_int *count;
|
||||
struct arg_int *tos;
|
||||
struct arg_str *host;
|
||||
struct arg_lit *abort;
|
||||
struct arg_end *end;
|
||||
} ping_args;
|
||||
|
||||
static int wifi_cmd_ping(int argc, char **argv)
|
||||
{
|
||||
esp_ping_config_t config = ESP_PING_DEFAULT_CONFIG();
|
||||
config.count = 0;
|
||||
config.data_size = 1;
|
||||
config.interval_ms = 10;
|
||||
config.task_stack_size = 3072;
|
||||
|
||||
if (arg_parse(argc, argv, (void **)&ping_args) != ESP_OK) {
|
||||
arg_print_errors(stderr, ping_args.end, argv[0]);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (ping_args.timeout->count > 0) {
|
||||
config.timeout_ms = ping_args.timeout->ival[0];
|
||||
}
|
||||
|
||||
if (ping_args.interval->count > 0) {
|
||||
config.interval_ms = ping_args.interval->ival[0];
|
||||
}
|
||||
|
||||
if (ping_args.data_size->count > 0) {
|
||||
config.data_size = ping_args.data_size->ival[0];
|
||||
}
|
||||
|
||||
if (ping_args.count->count > 0) {
|
||||
config.count = ping_args.count->ival[0];
|
||||
}
|
||||
|
||||
if (ping_args.tos->count > 0) {
|
||||
config.tos = ping_args.tos->ival[0];
|
||||
}
|
||||
|
||||
if (ping_args.abort->count > 0) {
|
||||
if (g_ping_handle != NULL) {
|
||||
ESP_LOGI(TAG, "Stopping ping session");
|
||||
esp_ping_stop(g_ping_handle);
|
||||
esp_ping_delete_session(g_ping_handle);
|
||||
g_ping_handle = NULL;
|
||||
ESP_LOGI(TAG, "Ping session stopped and deleted");
|
||||
} else {
|
||||
ESP_LOGW(TAG, "No active ping session to stop");
|
||||
}
|
||||
ESP_LOGW(TAG, "esp_ping stop");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
char host[32] = {0};
|
||||
|
||||
if (ping_args.host->count > 0) {
|
||||
strcpy(host, ping_args.host->sval[0]);
|
||||
} else {
|
||||
esp_netif_ip_info_t local_ip;
|
||||
esp_netif_get_ip_info(esp_netif_get_handle_from_ifkey("WIFI_STA_DEF"), &local_ip);
|
||||
sprintf(host, IPSTR, IP2STR(&local_ip.gw));
|
||||
ESP_LOGI(TAG, "ping router ip:" IPSTR ", gw: " IPSTR, IP2STR(&local_ip.ip), IP2STR(&local_ip.gw));
|
||||
}
|
||||
|
||||
// parse IP address
|
||||
struct sockaddr_in6 sock_addr6;
|
||||
ip_addr_t target_addr;
|
||||
memset(&target_addr, 0, sizeof(target_addr));
|
||||
|
||||
if (inet_pton(AF_INET6, host, &sock_addr6.sin6_addr) == 1) {
|
||||
/* convert ip6 string to ip6 address */
|
||||
ipaddr_aton(host, &target_addr);
|
||||
} else {
|
||||
struct addrinfo hint;
|
||||
struct addrinfo *res = NULL;
|
||||
memset(&hint, 0, sizeof(hint));
|
||||
|
||||
/* convert ip4 string or hostname to ip4 or ip6 address */
|
||||
if (getaddrinfo(host, NULL, &hint, &res) != 0) {
|
||||
printf("ping: unknown host %s\n", host);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (res->ai_family == AF_INET) {
|
||||
struct in_addr addr4 = ((struct sockaddr_in *)(res->ai_addr))->sin_addr;
|
||||
inet_addr_to_ip4addr(ip_2_ip4(&target_addr), &addr4);
|
||||
target_addr.type = IPADDR_TYPE_V4;
|
||||
} else {
|
||||
struct in6_addr addr6 = ((struct sockaddr_in6 *)(res->ai_addr))->sin6_addr;
|
||||
inet6_addr_to_ip6addr(ip_2_ip6(&target_addr), &addr6);
|
||||
target_addr.type = IPADDR_TYPE_V6;
|
||||
}
|
||||
|
||||
freeaddrinfo(res);
|
||||
}
|
||||
|
||||
config.target_addr = target_addr;
|
||||
|
||||
/* stop and delete existing ping session if any */
|
||||
if (g_ping_handle != NULL) {
|
||||
ESP_LOGI(TAG, "Stopping existing ping session before starting new one");
|
||||
esp_ping_stop(g_ping_handle);
|
||||
esp_ping_delete_session(g_ping_handle);
|
||||
g_ping_handle = NULL;
|
||||
ESP_LOGI(TAG, "Existing ping session stopped and deleted");
|
||||
}
|
||||
|
||||
/* set callback functions */
|
||||
esp_ping_callbacks_t cbs = {
|
||||
.on_ping_success = ping_cmd_on_success,
|
||||
.on_ping_timeout = ping_cmd_on_timeout,
|
||||
.on_ping_end = ping_cmd_on_end,
|
||||
.cb_args = NULL
|
||||
};
|
||||
|
||||
esp_ping_new_session(&config, &cbs, &g_ping_handle);
|
||||
esp_ping_start(g_ping_handle);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void cmd_register_ping(void)
|
||||
{
|
||||
ping_args.timeout = arg_int0("W", "timeout", "<t>", "Time to wait for a response, in seconds");
|
||||
ping_args.interval = arg_int0("i", "interval", "<t>", "Wait interval seconds between sending each packet");
|
||||
ping_args.data_size = arg_int0("s", "size", "<n>", "Specify the number of data bytes to be sent");
|
||||
ping_args.count = arg_int0("c", "count", "<n>", "Stop after sending count packets");
|
||||
ping_args.tos = arg_int0("Q", "tos", "<n>", "Set Type of Service related bits in IP datagrams");
|
||||
ping_args.host = arg_str0("h", "host", "<host>", "Host address");
|
||||
ping_args.abort = arg_lit0("a", "abort", "Abort running ping");
|
||||
ping_args.end = arg_end(10);
|
||||
const esp_console_cmd_t ping_cmd = {
|
||||
.command = "ping",
|
||||
.help = "Send ICMP ECHO_REQUEST to network hosts",
|
||||
.hint = NULL,
|
||||
.func = &wifi_cmd_ping,
|
||||
.argtable = &ping_args
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&ping_cmd));
|
||||
}
|
||||
264
esp-radar/console_test/components/commands/src/system_cmd.c
Normal file
264
esp-radar/console_test/components/commands/src/system_cmd.c
Normal file
@@ -0,0 +1,264 @@
|
||||
// Copyright 2017 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "esp_log.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
#include "argtable3/argtable3.h"
|
||||
#include "mbedtls/base64.h"
|
||||
|
||||
#include "esp_system.h"
|
||||
#include "esp_partition.h"
|
||||
#include "esp_console.h"
|
||||
#include "esp_chip_info.h"
|
||||
|
||||
|
||||
static const char *TAG = "system_cmd";
|
||||
|
||||
/**
|
||||
* @brief A function which implements version command.
|
||||
*/
|
||||
static int version_func(int argc, char **argv)
|
||||
{
|
||||
esp_chip_info_t chip_info = {0};
|
||||
|
||||
/**< Pint system information */
|
||||
esp_chip_info(&chip_info);
|
||||
ESP_LOGI(TAG, "compile time : %s %s", __DATE__, __TIME__);
|
||||
ESP_LOGI(TAG, "free heap : %d Bytes", esp_get_free_heap_size());
|
||||
ESP_LOGI(TAG, "CPU cores : %d", chip_info.cores);
|
||||
ESP_LOGI(TAG, "silicon revision : %d", chip_info.revision);
|
||||
ESP_LOGI(TAG, "feature : %s%s%s%s",
|
||||
chip_info.features & CHIP_FEATURE_WIFI_BGN ? "/802.11bgn" : "",
|
||||
chip_info.features & CHIP_FEATURE_BLE ? "/BLE" : "",
|
||||
chip_info.features & CHIP_FEATURE_BT ? "/BT" : "",
|
||||
chip_info.features & CHIP_FEATURE_EMB_FLASH ? "/Embedded-Flash:" : "/External-Flash:");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Register version command.
|
||||
*/
|
||||
static void register_version()
|
||||
{
|
||||
const esp_console_cmd_t cmd = {
|
||||
.command = "version",
|
||||
.help = "Get version of chip and SDK",
|
||||
.hint = NULL,
|
||||
.func = &version_func,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&cmd));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief A function which implements restart command.
|
||||
*/
|
||||
static int restart_func(int argc, char **argv)
|
||||
{
|
||||
ESP_LOGI(TAG, "Restarting");
|
||||
esp_restart();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Register restart command.
|
||||
*/
|
||||
static void register_restart()
|
||||
{
|
||||
const esp_console_cmd_t cmd = {
|
||||
.command = "restart",
|
||||
.help = "Software reset of the chip",
|
||||
.hint = NULL,
|
||||
.func = &restart_func,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&cmd));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief A function which implements reset command.
|
||||
*/
|
||||
static int reset_func(int argc, char **argv)
|
||||
{
|
||||
esp_partition_iterator_t part_itra = NULL;
|
||||
const esp_partition_t *nvs_part = NULL;
|
||||
|
||||
ESP_LOGI(TAG, "Erase part of the nvs partition");
|
||||
|
||||
part_itra = esp_partition_find(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "nvs");
|
||||
nvs_part = esp_partition_get(part_itra);
|
||||
esp_partition_erase_range(nvs_part, 0, nvs_part->size);
|
||||
|
||||
ESP_LOGI(TAG, "Restarting");
|
||||
esp_restart();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Register reset command.
|
||||
*/
|
||||
static void register_reset()
|
||||
{
|
||||
const esp_console_cmd_t cmd = {
|
||||
.command = "reset",
|
||||
.help = "Clear device configuration information",
|
||||
.hint = NULL,
|
||||
.func = &reset_func,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&cmd));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief A function which implements heap command.
|
||||
*/
|
||||
static int heap_func(int argc, char **argv)
|
||||
{
|
||||
#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
|
||||
TaskStatus_t *pxTaskStatusArray = NULL;
|
||||
volatile UBaseType_t uxArraySize = 0;
|
||||
uint32_t ulTotalRunTime = 0, ulStatsAsPercentage = 0, ulRunTimeCounte = 0;
|
||||
const char task_status_char[] = {'r', 'R', 'B', 'S', 'D'};
|
||||
|
||||
/* Take a snapshot of the number of tasks in case it changes while this
|
||||
function is executing. */
|
||||
uxArraySize = uxTaskGetNumberOfTasks();
|
||||
pxTaskStatusArray = malloc(uxTaskGetNumberOfTasks() * sizeof(TaskStatus_t));
|
||||
|
||||
if (!pxTaskStatusArray) {
|
||||
return ;
|
||||
}
|
||||
|
||||
/* Generate the (binary) data. */
|
||||
uxArraySize = uxTaskGetSystemState(pxTaskStatusArray, uxArraySize, &ulTotalRunTime);
|
||||
ulTotalRunTime /= 100UL;
|
||||
|
||||
ESP_LOGI(TAG, "---------------- The State Of Tasks ----------------");
|
||||
ESP_LOGI(TAG, "- HWM : usage high water mark (Byte)");
|
||||
ESP_LOGI(TAG, "- Status: blocked ('B'), ready ('R'), deleted ('D') or suspended ('S')\n");
|
||||
ESP_LOGI(TAG, "TaskName\t\tStatus\tPrio\tHWM\tTaskNum\tCoreID\tRunTimeCounter\tPercentage");
|
||||
|
||||
for (int i = 0; i < uxArraySize; i++) {
|
||||
#if( configGENERATE_RUN_TIME_STATS == 1 )
|
||||
ulRunTimeCounte = pxTaskStatusArray[i].ulRunTimeCounter;
|
||||
ulStatsAsPercentage = ulRunTimeCounte / ulTotalRunTime;
|
||||
#else
|
||||
#warning configGENERATE_RUN_TIME_STATS must also be set to 1 in FreeRTOSConfig.h to use vTaskGetRunTimeStats().
|
||||
#endif
|
||||
|
||||
int core_id = -1;
|
||||
char precentage_char[4] = {0};
|
||||
|
||||
#if ( configTASKLIST_INCLUDE_COREID == 1 )
|
||||
core_id = (int) pxTaskStatusArray[ i ].xCoreID;
|
||||
#else
|
||||
#warning configTASKLIST_INCLUDE_COREID must also be set to 1 in FreeRTOSConfig.h to use xCoreID.
|
||||
#endif
|
||||
|
||||
/* Write the rest of the string. */
|
||||
ESP_LOGI(TAG, "%-16s\t%c\t%u\t%u\t%u\t%hd\t%-16u%-s%%",
|
||||
pxTaskStatusArray[i].pcTaskName, task_status_char[pxTaskStatusArray[i].eCurrentState],
|
||||
(uint32_t) pxTaskStatusArray[i].uxCurrentPriority,
|
||||
(uint32_t) pxTaskStatusArray[i].usStackHighWaterMark,
|
||||
(uint32_t) pxTaskStatusArray[i].xTaskNumber, core_id,
|
||||
ulRunTimeCounte, (ulStatsAsPercentage <= 0) ? "<1" : itoa(ulStatsAsPercentage, precentage_char, 10));
|
||||
}
|
||||
|
||||
free(pxTaskStatusArray);
|
||||
#endif /**< ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 */
|
||||
|
||||
#ifndef CONFIG_SPIRAM_SUPPORT
|
||||
ESP_LOGI(TAG, "Free heap, current: %d, minimum: %d",
|
||||
esp_get_free_heap_size(), esp_get_minimum_free_heap_size());
|
||||
#else
|
||||
ESP_LOGI(TAG, "Free heap, internal current: %d, minimum: %d, total current: %d, minimum: %d",
|
||||
heap_caps_get_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL),
|
||||
heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL),
|
||||
esp_get_free_heap_size(), esp_get_minimum_free_heap_size());
|
||||
#endif /**< CONFIG_SPIRAM_SUPPORT */
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Register heap command.
|
||||
*/
|
||||
static void register_heap()
|
||||
{
|
||||
const esp_console_cmd_t cmd = {
|
||||
.command = "heap",
|
||||
.help = "Get the current size of free heap memory",
|
||||
.hint = NULL,
|
||||
.func = &heap_func,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&cmd));
|
||||
}
|
||||
|
||||
|
||||
|
||||
static struct {
|
||||
struct arg_str *tag;
|
||||
struct arg_str *level;
|
||||
struct arg_end *end;
|
||||
} log_args;
|
||||
|
||||
/**
|
||||
* @brief A function which implements log command.
|
||||
*/
|
||||
static int log_func(int argc, char **argv)
|
||||
{
|
||||
const char *level_str[6] = {"NONE", "ERR", "WARN", "INFO", "DEBUG", "VER"};
|
||||
|
||||
if (arg_parse(argc, argv, (void **)&log_args) != ESP_OK) {
|
||||
arg_print_errors(stderr, log_args.end, argv[0]);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
for (int log_level = 0; log_args.level->count && log_level < sizeof(level_str) / sizeof(char *); ++log_level) {
|
||||
if (!strncasecmp(level_str[log_level], log_args.level->sval[0], sizeof(level_str[log_level]) - 1)) {
|
||||
const char *tag = log_args.tag->count ? log_args.tag->sval[0] : "*";
|
||||
esp_log_level_set(tag, log_level);
|
||||
}
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Register log command.
|
||||
*/
|
||||
static void register_log()
|
||||
{
|
||||
log_args.tag = arg_str0("t", "tag", "<tag>", "Tag of the log entries to enable, '*' resets log level for all tags to the given value");
|
||||
log_args.level = arg_str0("l", "level", "<level>", "Selects log level to enable (NONE, ERR, WARN, INFO, DEBUG, VER)");
|
||||
log_args.end = arg_end(2);
|
||||
|
||||
const esp_console_cmd_t cmd = {
|
||||
.command = "log",
|
||||
.help = "Set log level for given tag",
|
||||
.hint = NULL,
|
||||
.func = &log_func,
|
||||
.argtable = &log_args,
|
||||
};
|
||||
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&cmd));
|
||||
}
|
||||
|
||||
void cmd_register_system(void)
|
||||
{
|
||||
register_version();
|
||||
register_heap();
|
||||
register_restart();
|
||||
register_reset();
|
||||
register_log();
|
||||
}
|
||||
580
esp-radar/console_test/components/commands/src/wifi_cmd.c
Normal file
580
esp-radar/console_test/components/commands/src/wifi_cmd.c
Normal file
@@ -0,0 +1,580 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "nvs_flash.h"
|
||||
#include "argtable3/argtable3.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/event_groups.h"
|
||||
|
||||
#include "esp_mac.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_console.h"
|
||||
#include "esp_netif.h"
|
||||
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/netdb.h"
|
||||
#include "lwip/sockets.h"
|
||||
|
||||
#define WIFI_CONNECTED_BIT BIT0
|
||||
#define WIFI_DISCONNECTED_BIT BIT1
|
||||
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0)
|
||||
#define ESP_IF_WIFI_STA ESP_MAC_WIFI_STA
|
||||
#endif
|
||||
|
||||
static bool s_reconnect = true;
|
||||
static const char *TAG = "wifi_cmd";
|
||||
|
||||
static EventGroupHandle_t s_wifi_event_group;
|
||||
|
||||
static bool mac_str2hex(const char *mac_str, uint8_t *mac_hex)
|
||||
{
|
||||
uint32_t mac_data[6] = {0};
|
||||
int ret = sscanf(mac_str, MACSTR, mac_data, mac_data + 1, mac_data + 2,
|
||||
mac_data + 3, mac_data + 4, mac_data + 5);
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
mac_hex[i] = mac_data[i];
|
||||
}
|
||||
|
||||
return ret == 6 ? true : false;
|
||||
}
|
||||
|
||||
/* Event handler for catching system events */
|
||||
static void wifi_event_handler(void *arg, esp_event_base_t event_base,
|
||||
int32_t event_id, void *event_data)
|
||||
{
|
||||
if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
|
||||
xEventGroupClearBits(s_wifi_event_group, WIFI_DISCONNECTED_BIT);
|
||||
xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
|
||||
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
|
||||
if (s_reconnect) {
|
||||
ESP_LOGI(TAG, "sta disconnect, s_reconnect...");
|
||||
esp_wifi_connect();
|
||||
} else {
|
||||
// ESP_LOGI(TAG, "sta disconnect");
|
||||
}
|
||||
|
||||
xEventGroupClearBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
|
||||
xEventGroupSetBits(s_wifi_event_group, WIFI_DISCONNECTED_BIT);
|
||||
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_CONNECTED) {
|
||||
wifi_event_sta_connected_t *event = (wifi_event_sta_connected_t *)event_data;
|
||||
ESP_LOGI(TAG, "Connected to %s (bssid: "MACSTR", channel: %d)", event->ssid,
|
||||
MAC2STR(event->bssid), event->channel);
|
||||
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_AP_STACONNECTED) {
|
||||
ESP_LOGI(TAG, "STA Connecting to the AP again...");
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
struct arg_str *ssid;
|
||||
struct arg_str *password;
|
||||
struct arg_end *end;
|
||||
} wifi_args_t;
|
||||
|
||||
static wifi_args_t sta_args;
|
||||
static wifi_args_t ap_args;
|
||||
|
||||
static int wifi_cmd_sta(int argc, char **argv)
|
||||
{
|
||||
if (arg_parse(argc, argv, (void **) &sta_args) != ESP_OK) {
|
||||
arg_print_errors(stderr, sta_args.end, argv[0]);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
const char *ssid = sta_args.ssid->sval[0];
|
||||
const char *password = sta_args.password->sval[0];
|
||||
wifi_config_t wifi_config = { 0 };
|
||||
static esp_netif_t *s_netif_sta = NULL;
|
||||
|
||||
if (!s_wifi_event_group) {
|
||||
s_wifi_event_group = xEventGroupCreate();
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL));
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &wifi_event_handler, NULL));
|
||||
}
|
||||
|
||||
if (!s_netif_sta) {
|
||||
// 检查是否已经存在默认的STA netif(可能由esp_radar_wifi_init创建)
|
||||
s_netif_sta = esp_netif_get_handle_from_ifkey("WIFI_STA_DEF");
|
||||
if (!s_netif_sta) {
|
||||
s_netif_sta = esp_netif_create_default_wifi_sta();
|
||||
}
|
||||
}
|
||||
|
||||
strlcpy((char *) wifi_config.sta.ssid, ssid, sizeof(wifi_config.sta.ssid));
|
||||
|
||||
if (password) {
|
||||
strlcpy((char *) wifi_config.sta.password, password, sizeof(wifi_config.sta.password));
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "sta connecting to '%s'", ssid);
|
||||
|
||||
int bits = xEventGroupWaitBits(s_wifi_event_group, WIFI_CONNECTED_BIT, false, true, false);
|
||||
|
||||
if (bits & WIFI_CONNECTED_BIT) {
|
||||
s_reconnect = false;
|
||||
xEventGroupClearBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
|
||||
ESP_ERROR_CHECK(esp_wifi_disconnect());
|
||||
xEventGroupWaitBits(s_wifi_event_group, WIFI_DISCONNECTED_BIT, false, true, portMAX_DELAY);
|
||||
}
|
||||
|
||||
s_reconnect = true;
|
||||
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
|
||||
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config));
|
||||
esp_wifi_connect();
|
||||
|
||||
xEventGroupWaitBits(s_wifi_event_group, WIFI_CONNECTED_BIT, false, true, pdMS_TO_TICKS(5000));
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static int wifi_cmd_ap(int argc, char **argv)
|
||||
{
|
||||
if (arg_parse(argc, argv, (void **) &ap_args) != ESP_OK) {
|
||||
arg_print_errors(stderr, ap_args.end, argv[0]);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
wifi_config_t wifi_config = {
|
||||
.ap = {
|
||||
.ssid = "",
|
||||
.ssid_len = 0,
|
||||
.max_connection = 4,
|
||||
.password = "",
|
||||
.channel = 11,
|
||||
},
|
||||
};
|
||||
|
||||
const char *ssid = ap_args.ssid->sval[0];
|
||||
const char *password = ap_args.password->sval[0];
|
||||
static esp_netif_t *s_netif_ap = NULL;
|
||||
|
||||
if (!s_wifi_event_group) {
|
||||
s_wifi_event_group = xEventGroupCreate();
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL));
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &wifi_event_handler, NULL));
|
||||
}
|
||||
|
||||
if (!s_netif_ap) {
|
||||
s_netif_ap = esp_netif_create_default_wifi_ap();
|
||||
}
|
||||
|
||||
s_reconnect = false;
|
||||
strlcpy((char *) wifi_config.ap.ssid, ssid, sizeof(wifi_config.ap.ssid));
|
||||
|
||||
if (password && strlen(password)) {
|
||||
if (strlen(password) < 8) {
|
||||
s_reconnect = true;
|
||||
ESP_LOGE(TAG, "password less than 8");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
wifi_config.ap.authmode = WIFI_AUTH_WPA2_PSK;
|
||||
strlcpy((char *) wifi_config.ap.password, password, sizeof(wifi_config.ap.password));
|
||||
}
|
||||
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
|
||||
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_AP, &wifi_config));
|
||||
|
||||
ESP_LOGI(TAG, "Starting SoftAP SSID: %s, Password: %s", ssid, password);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static int wifi_cmd_query(int argc, char **argv)
|
||||
{
|
||||
wifi_config_t cfg;
|
||||
wifi_mode_t mode;
|
||||
|
||||
esp_wifi_get_mode(&mode);
|
||||
|
||||
if (WIFI_MODE_AP == mode) {
|
||||
esp_wifi_get_config(WIFI_IF_AP, &cfg);
|
||||
ESP_LOGI(TAG, "AP mode, %s %s", cfg.ap.ssid, cfg.ap.password);
|
||||
} else if (WIFI_MODE_STA == mode) {
|
||||
int bits = xEventGroupWaitBits(s_wifi_event_group, WIFI_CONNECTED_BIT, 0, 1, 0);
|
||||
|
||||
if (bits & WIFI_CONNECTED_BIT) {
|
||||
esp_wifi_get_config(WIFI_IF_STA, &cfg);
|
||||
ESP_LOGI(TAG, "sta mode, connected %s", cfg.ap.ssid);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "sta mode, disconnected");
|
||||
}
|
||||
} else {
|
||||
ESP_LOGI(TAG, "NULL mode");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cmd_register_wifi(void)
|
||||
{
|
||||
sta_args.ssid = arg_str1(NULL, NULL, "<ssid>", "SSID of AP");
|
||||
sta_args.password = arg_str0(NULL, NULL, "<password>", "password of AP");
|
||||
sta_args.end = arg_end(2);
|
||||
|
||||
const esp_console_cmd_t sta_cmd = {
|
||||
.command = "sta",
|
||||
.help = "WiFi is station mode, join specified soft-AP",
|
||||
.hint = NULL,
|
||||
.func = &wifi_cmd_sta,
|
||||
.argtable = &sta_args
|
||||
};
|
||||
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&sta_cmd));
|
||||
|
||||
ap_args.ssid = arg_str1(NULL, NULL, "<ssid>", "SSID of AP");
|
||||
ap_args.password = arg_str0(NULL, NULL, "<password>", "password of AP");
|
||||
ap_args.end = arg_end(2);
|
||||
|
||||
const esp_console_cmd_t ap_cmd = {
|
||||
.command = "ap",
|
||||
.help = "AP mode, configure ssid and password",
|
||||
.hint = NULL,
|
||||
.func = &wifi_cmd_ap,
|
||||
.argtable = &ap_args
|
||||
};
|
||||
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&ap_cmd));
|
||||
|
||||
const esp_console_cmd_t query_cmd = {
|
||||
.command = "query",
|
||||
.help = "query WiFi info",
|
||||
.hint = NULL,
|
||||
.func = &wifi_cmd_query,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&query_cmd));
|
||||
}
|
||||
|
||||
static struct {
|
||||
struct arg_str *country_code;
|
||||
struct arg_int *channel;
|
||||
struct arg_int *channel_second;
|
||||
struct arg_str *ssid;
|
||||
struct arg_str *bssid;
|
||||
struct arg_str *password;
|
||||
struct arg_lit *disconnect;
|
||||
struct arg_int *tx_power;
|
||||
struct arg_lit *info;
|
||||
struct arg_int *rate;
|
||||
struct arg_int *bandwidth;
|
||||
struct arg_int *protocol;
|
||||
struct arg_end *end;
|
||||
} wifi_config_args;
|
||||
|
||||
/**
|
||||
* @brief A function which implements wifi config command.
|
||||
*/
|
||||
static int wifi_config_func(int argc, char **argv)
|
||||
{
|
||||
if (arg_parse(argc, argv, (void **) &wifi_config_args) != ESP_OK) {
|
||||
arg_print_errors(stderr, wifi_config_args.end, argv[0]);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (!s_wifi_event_group) {
|
||||
s_wifi_event_group = xEventGroupCreate();
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL));
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &wifi_event_handler, NULL));
|
||||
}
|
||||
|
||||
if (wifi_config_args.disconnect->count) {
|
||||
s_reconnect = false;
|
||||
esp_wifi_disconnect();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t ret = ESP_OK;
|
||||
wifi_config_t wifi_config = {0x0};
|
||||
esp_wifi_get_config(WIFI_IF_STA, &wifi_config);
|
||||
static esp_netif_t *s_netif_sta = NULL;
|
||||
|
||||
wifi_mode_t mode;
|
||||
esp_wifi_get_mode(&mode);
|
||||
|
||||
if (!s_netif_sta && mode != WIFI_MODE_STA) {
|
||||
// 检查是否已经存在默认的STA netif(可能由esp_radar_wifi_init创建)
|
||||
s_netif_sta = esp_netif_get_handle_from_ifkey("WIFI_STA_DEF");
|
||||
if (!s_netif_sta) {
|
||||
s_netif_sta = esp_netif_create_default_wifi_sta();
|
||||
}
|
||||
}
|
||||
|
||||
if (wifi_config_args.ssid->count) {
|
||||
strcpy((char *)wifi_config.sta.ssid, wifi_config_args.ssid->sval[0]);
|
||||
}
|
||||
|
||||
if (wifi_config_args.password->count) {
|
||||
strcpy((char *)wifi_config.sta.password, wifi_config_args.password->sval[0]);
|
||||
}
|
||||
|
||||
if (wifi_config_args.bssid->count) {
|
||||
if (!mac_str2hex(wifi_config_args.bssid->sval[0], wifi_config.sta.bssid)) {
|
||||
ESP_LOGE(TAG, "The format of the address is incorrect. Please enter the format as xx:xx:xx:xx:xx:xx");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
if (strlen((char *)wifi_config.sta.ssid)) {
|
||||
int bits = xEventGroupWaitBits(s_wifi_event_group, WIFI_CONNECTED_BIT, false, true, false);
|
||||
|
||||
if (bits & WIFI_CONNECTED_BIT) {
|
||||
s_reconnect = false;
|
||||
xEventGroupClearBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
|
||||
ESP_ERROR_CHECK(esp_wifi_disconnect());
|
||||
xEventGroupWaitBits(s_wifi_event_group, WIFI_DISCONNECTED_BIT, false, true, portMAX_DELAY);
|
||||
}
|
||||
|
||||
s_reconnect = true;
|
||||
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
|
||||
// esp_err_t esp_wifi_internal_set_fix_rate(wifi_interface_t ifx, bool en, wifi_phy_rate_t rate);
|
||||
// esp_wifi_internal_set_fix_rate(ESP_IF_WIFI_STA, true, WIFI_PHY_RATE_48M);
|
||||
// ESP_LOGW(TAG, "------- <%s, %d> ------", __func__, __LINE__);
|
||||
|
||||
// ESP_ERROR_CHECK(esp_wifi_set_bandwidth(WIFI_IF_STA, WIFI_BW_HT20));
|
||||
|
||||
// ESP_ERROR_CHECK(esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G));
|
||||
|
||||
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
|
||||
esp_wifi_connect();
|
||||
xEventGroupWaitBits(s_wifi_event_group, WIFI_CONNECTED_BIT, false, true, pdMS_TO_TICKS(5000));
|
||||
}
|
||||
|
||||
if (wifi_config_args.country_code->count) {
|
||||
wifi_country_t country = {0};
|
||||
const char *country_code = wifi_config_args.country_code->sval[0];
|
||||
|
||||
if (!strcasecmp(country_code, "US")) {
|
||||
strcpy(country.cc, "US");
|
||||
country.schan = 1;
|
||||
country.nchan = 11;
|
||||
} else if (!strcasecmp(country_code, "JP")) {
|
||||
strcpy(country.cc, "JP");
|
||||
country.schan = 1;
|
||||
country.nchan = 14;
|
||||
} else if (!strcasecmp(country_code, "CN")) {
|
||||
strcpy(country.cc, "CN");
|
||||
country.schan = 1;
|
||||
country.nchan = 13;
|
||||
} else {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
ret = esp_wifi_set_country(&country);
|
||||
}
|
||||
|
||||
if (wifi_config_args.channel->count) {
|
||||
wifi_config.sta.channel = wifi_config_args.channel->ival[0];
|
||||
wifi_second_chan_t second = WIFI_SECOND_CHAN_NONE;
|
||||
|
||||
if (wifi_config_args.channel_second->count < 3) {
|
||||
second = wifi_config_args.channel_second->ival[0];
|
||||
}
|
||||
|
||||
if (wifi_config.sta.channel > 0 && wifi_config.sta.channel <= 14) {
|
||||
ret = esp_wifi_set_channel(wifi_config.sta.channel, second);
|
||||
|
||||
if (ret == ESP_OK) {
|
||||
ESP_LOGI(TAG, "Set Channel, channel: %d", wifi_config.sta.channel);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "<%s> esp_wifi_set_channel", esp_err_to_name(ret));
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
} else {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
if (wifi_config_args.tx_power->count) {
|
||||
esp_wifi_set_max_tx_power(wifi_config_args.tx_power->ival[0]);
|
||||
}
|
||||
|
||||
if (wifi_config_args.info->count) {
|
||||
int8_t rx_power = 0;
|
||||
wifi_country_t country = {0};
|
||||
uint8_t primary = 0;
|
||||
wifi_second_chan_t second = 0;
|
||||
wifi_mode_t mode = 0;
|
||||
wifi_bandwidth_t bandwidth = 0;
|
||||
|
||||
esp_wifi_get_channel(&primary, &second);
|
||||
esp_wifi_get_max_tx_power(&rx_power);
|
||||
esp_wifi_get_country(&country);
|
||||
esp_wifi_get_mode(&mode);
|
||||
esp_wifi_get_bandwidth(mode - 1, &bandwidth);
|
||||
|
||||
country.cc[2] = '\0';
|
||||
ESP_LOGI(TAG, "tx_power: %d, country: %s, channel: %d/%d, mode: %d, bandwidth: %d",
|
||||
rx_power, country.cc, primary, second, mode, bandwidth);
|
||||
}
|
||||
|
||||
if (wifi_config_args.bandwidth->count) {
|
||||
ESP_ERROR_CHECK(esp_wifi_set_bandwidth(ESP_IF_WIFI_STA, wifi_config_args.bandwidth->ival[0]));
|
||||
}
|
||||
|
||||
if (wifi_config_args.rate->count) {
|
||||
extern esp_err_t esp_wifi_internal_set_fix_rate(wifi_interface_t ifx, bool en, wifi_phy_rate_t rate);
|
||||
ESP_ERROR_CHECK(esp_wifi_internal_set_fix_rate(ESP_IF_WIFI_STA, true, wifi_config_args.rate->ival[0]));
|
||||
}
|
||||
|
||||
if (wifi_config_args.protocol->count) {
|
||||
ESP_ERROR_CHECK(esp_wifi_set_protocol(ESP_IF_WIFI_STA, wifi_config_args.protocol->ival[0]));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Register wifi config command.
|
||||
*/
|
||||
void cmd_register_wifi_config()
|
||||
{
|
||||
wifi_config_args.ssid = arg_str0("s", "ssid", "<ssid>", "SSID of router");
|
||||
wifi_config_args.password = arg_str0("p", "password", "<password>", "Password of router");
|
||||
wifi_config_args.bssid = arg_str0("b", "bssid", "<bssid (xx:xx:xx:xx:xx:xx)>", "BSSID of router");
|
||||
wifi_config_args.disconnect = arg_lit0("d", "disconnect", "Disconnect the router");
|
||||
wifi_config_args.channel = arg_int0("c", "channel", "<channel (1 ~ 14)>", "Set primary channel");
|
||||
wifi_config_args.channel_second = arg_int0("c", "channel_second", "<channel_second (0, 1, 2)>", "Set second channel");
|
||||
wifi_config_args.country_code = arg_str0("C", "country_code", "<country_code ('CN', 'JP, 'US')>", "Set the current country code");
|
||||
wifi_config_args.tx_power = arg_int0("t", "tx_power", "<power (8 ~ 84)>", "Set maximum transmitting power after WiFi start.");
|
||||
wifi_config_args.rate = arg_int0("r", "rate", "<MCS>", "Set the bandwidth of ESP32 specified interface");
|
||||
wifi_config_args.bandwidth = arg_int0("w", "bandwidth", "<bandwidth(1: HT20, 2: HT40)>", "Set the bandwidth of ESP32 specified interface");
|
||||
wifi_config_args.protocol = arg_int0("P", "protocol", "<bgn(1,3,7)>", "Set protocol type of specified interface");
|
||||
wifi_config_args.info = arg_lit0("i", "info", "Get Wi-Fi configuration information");
|
||||
wifi_config_args.end = arg_end(10);
|
||||
|
||||
const esp_console_cmd_t cmd = {
|
||||
.command = "wifi_config",
|
||||
.help = "Set the configuration of the ESP32 STA",
|
||||
.hint = NULL,
|
||||
.func = &wifi_config_func,
|
||||
.argtable = &wifi_config_args,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&cmd));
|
||||
}
|
||||
|
||||
static struct {
|
||||
struct arg_int *rssi;
|
||||
struct arg_str *ssid;
|
||||
struct arg_str *bssid;
|
||||
struct arg_int *passive;
|
||||
struct arg_end *end;
|
||||
} wifi_scan_args;
|
||||
|
||||
/**
|
||||
* @brief A function which implements wifi scan command.
|
||||
*/
|
||||
static esp_err_t wifi_scan_func(int argc, char **argv)
|
||||
{
|
||||
if (arg_parse(argc, argv, (void **) &wifi_scan_args) != ESP_OK) {
|
||||
arg_print_errors(stderr, wifi_scan_args.end, argv[0]);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
int8_t filter_rssi = -120;
|
||||
uint16_t ap_number = 0;
|
||||
uint8_t bssid[6] = {0x0};
|
||||
uint8_t channel = 1;
|
||||
wifi_second_chan_t second = 0;
|
||||
wifi_ap_record_t ap_record = {0x0};
|
||||
wifi_scan_config_t scan_config = {
|
||||
.show_hidden = true,
|
||||
.scan_type = WIFI_SCAN_TYPE_ACTIVE,
|
||||
};
|
||||
|
||||
ESP_ERROR_CHECK(esp_wifi_get_channel(&channel, &second));
|
||||
ESP_ERROR_CHECK(esp_wifi_disconnect());
|
||||
|
||||
if (wifi_scan_args.passive->count) {
|
||||
scan_config.scan_type = WIFI_SCAN_TYPE_PASSIVE;
|
||||
scan_config.scan_time.passive = wifi_scan_args.passive->ival[0];
|
||||
}
|
||||
|
||||
if (wifi_scan_args.ssid->count) {
|
||||
scan_config.ssid = (uint8_t *)wifi_scan_args.ssid->sval[0];
|
||||
}
|
||||
|
||||
if (wifi_scan_args.bssid->count) {
|
||||
if (!mac_str2hex(wifi_scan_args.bssid->sval[0], bssid)) {
|
||||
ESP_LOGE(TAG, "The format of the address is incorrect. Please enter the format as xx:xx:xx:xx:xx:xx");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
scan_config.bssid = bssid;
|
||||
}
|
||||
|
||||
if (wifi_scan_args.rssi->count) {
|
||||
filter_rssi = wifi_scan_args.rssi->ival[0];
|
||||
ESP_LOGW(TAG, "filter_rssi: %d", filter_rssi);
|
||||
}
|
||||
|
||||
esp_wifi_scan_stop();
|
||||
|
||||
int retry_count = 20;
|
||||
|
||||
do {
|
||||
esp_wifi_disconnect();
|
||||
esp_wifi_scan_start(&scan_config, true);
|
||||
esp_wifi_scan_get_ap_num(&ap_number);
|
||||
} while (ap_number <= 0 && --retry_count);
|
||||
|
||||
if (ap_number <= 0) {
|
||||
ESP_LOGE(TAG, "esp_wifi_scan_get_ap_num");
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Get number of APs found, number: %d", ap_number);
|
||||
|
||||
for (int i = 0; i < ap_number; i++) {
|
||||
memset(&ap_record, 0, sizeof(wifi_ap_record_t));
|
||||
|
||||
if (ap_record.rssi < filter_rssi) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Router, ssid: %s, bssid: " MACSTR ", channel: %u, rssi: %d",
|
||||
ap_record.ssid, MAC2STR(ap_record.bssid),
|
||||
ap_record.primary, ap_record.rssi);
|
||||
}
|
||||
|
||||
if (channel > 0 && channel < 13) {
|
||||
ESP_ERROR_CHECK(esp_wifi_set_channel(channel, second));
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Register wifi scan command.
|
||||
*/
|
||||
void cmd_register_wifi_scan()
|
||||
{
|
||||
wifi_scan_args.rssi = arg_int0("r", "rssi", "<rssi (-120 ~ 0)>", "Filter device uses RSSI");
|
||||
wifi_scan_args.ssid = arg_str0("s", "ssid", "<ssid>", "Filter device uses SSID");
|
||||
wifi_scan_args.bssid = arg_str0("b", "bssid", "<bssid (xx:xx:xx:xx:xx:xx)>", "Filter device uses AP's MAC");
|
||||
wifi_scan_args.passive = arg_int0("p", "passive", "<time (ms)>", "Passive scan time per channel");
|
||||
wifi_scan_args.end = arg_end(5);
|
||||
|
||||
const esp_console_cmd_t cmd = {
|
||||
.command = "wifi_scan",
|
||||
.help = "Wi-Fi is station mode, start scan ap",
|
||||
.hint = NULL,
|
||||
.func = &wifi_scan_func,
|
||||
.argtable = &wifi_scan_args,
|
||||
};
|
||||
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&cmd));
|
||||
}
|
||||
10
esp-radar/console_test/esp_csi_tool_gui.py
Normal file
10
esp-radar/console_test/esp_csi_tool_gui.py
Normal file
@@ -0,0 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'esp_csi_tool_gui.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.15.6
|
||||
#
|
||||
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
||||
# run again. Do not edit this file unless you know what you are doing.
|
||||
|
||||
|
||||
3
esp-radar/console_test/main/CMakeLists.txt
Normal file
3
esp-radar/console_test/main/CMakeLists.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
idf_component_register(SRC_DIRS "."
|
||||
INCLUDE_DIRS ".")
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
|
||||
16
esp-radar/console_test/main/Kconfig.projbuild
Normal file
16
esp-radar/console_test/main/Kconfig.projbuild
Normal file
@@ -0,0 +1,16 @@
|
||||
menu "WiFi Sensing Device Config"
|
||||
|
||||
config DEVICE_NAME
|
||||
string "Device Name"
|
||||
default "esp32-sensor"
|
||||
help
|
||||
Human-readable name for this ESP32 sensor device.
|
||||
This name will be included in CSI_DATA packets.
|
||||
|
||||
config DEVICE_LOCATION
|
||||
string "Device Location"
|
||||
default "room1"
|
||||
help
|
||||
Location identifier for this device (e.g., "living_room", "bedroom").
|
||||
|
||||
endmenu
|
||||
730
esp-radar/console_test/main/app_main.c
Normal file
730
esp-radar/console_test/main/app_main.c
Normal file
@@ -0,0 +1,730 @@
|
||||
/*
|
||||
* 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_log.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_console.h"
|
||||
|
||||
#include "esp_mac.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/netdb.h"
|
||||
#include "lwip/sockets.h"
|
||||
#include "ping/ping_sock.h"
|
||||
#include "hal/uart_ll.h"
|
||||
#include "mbedtls/base64.h"
|
||||
|
||||
#include "led_strip.h"
|
||||
#include "esp_radar.h"
|
||||
#include "csi_commands.h"
|
||||
|
||||
extern esp_ping_handle_t g_ping_handle;
|
||||
static led_strip_handle_t led_strip;
|
||||
#if CONFIG_IDF_TARGET_ESP32C5
|
||||
#define WS2812_GPIO 27
|
||||
#elif CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32C61
|
||||
#define WS2812_GPIO 8
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
#define WS2812_GPIO 38
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#define WS2812_GPIO 18
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||
#define WS2812_GPIO 8
|
||||
#else
|
||||
#define WS2812_GPIO 4
|
||||
#endif
|
||||
#define RECV_ESPNOW_CSI
|
||||
#define CONFIG_LESS_INTERFERENCE_CHANNEL 11
|
||||
#define CONFIG_SEND_DATA_FREQUENCY 100
|
||||
|
||||
#define RADAR_EVALUATE_SERVER_PORT 3232
|
||||
#define RADAR_BUFF_MAX_LEN 25
|
||||
|
||||
static QueueHandle_t g_csi_info_queue = NULL;
|
||||
static bool g_wifi_connect_status = false;
|
||||
static uint32_t g_send_data_interval = 1000 / CONFIG_SEND_DATA_FREQUENCY;
|
||||
static const char *TAG = "app_main";
|
||||
|
||||
static struct {
|
||||
struct arg_lit *train_start;
|
||||
struct arg_lit *train_stop;
|
||||
struct arg_lit *train_add;
|
||||
struct arg_str *predict_someone_threshold;
|
||||
struct arg_str *predict_someone_sensitivity;
|
||||
struct arg_str *predict_move_threshold;
|
||||
struct arg_str *predict_move_sensitivity;
|
||||
struct arg_int *predict_buff_size;
|
||||
struct arg_int *predict_outliers_number;
|
||||
struct arg_str *collect_taget;
|
||||
struct arg_int *collect_number;
|
||||
struct arg_int *collect_duration;
|
||||
struct arg_lit *csi_start;
|
||||
struct arg_lit *csi_stop;
|
||||
struct arg_str *csi_output_type;
|
||||
struct arg_str *csi_output_format;
|
||||
struct arg_int *csi_scale_shift;
|
||||
struct arg_int *channel_filter;
|
||||
struct arg_int *send_data_interval;
|
||||
struct arg_end *end;
|
||||
} radar_args;
|
||||
static struct console_input_config {
|
||||
bool train_start;
|
||||
float predict_someone_threshold;
|
||||
float predict_someone_sensitivity;
|
||||
float predict_move_threshold;
|
||||
float predict_move_sensitivity;
|
||||
uint32_t predict_buff_size;
|
||||
uint32_t predict_outliers_number;
|
||||
char collect_taget[16];
|
||||
uint32_t collect_number;
|
||||
char csi_output_type[16];
|
||||
char csi_output_format[16];
|
||||
} g_console_input_config = {
|
||||
.predict_someone_threshold = 0,
|
||||
.predict_someone_sensitivity = 0.15,
|
||||
.predict_move_threshold = 0.0003,
|
||||
.predict_move_sensitivity = 0.20,
|
||||
.predict_buff_size = 5,
|
||||
.predict_outliers_number = 2,
|
||||
.train_start = false,
|
||||
.collect_taget = "unknown",
|
||||
.csi_output_type = "LLTF",
|
||||
.csi_output_format = "decimal"
|
||||
};
|
||||
|
||||
static TimerHandle_t g_collect_timer_handele = NULL;
|
||||
|
||||
void wifi_csi_raw_cb(void *ctx, const wifi_csi_filtered_info_t *info)
|
||||
{
|
||||
wifi_csi_filtered_info_t *q_data = malloc(sizeof(wifi_csi_filtered_info_t) + info->valid_len);
|
||||
*q_data = *info;
|
||||
memcpy(q_data->valid_data, info->valid_data, info->valid_len);
|
||||
|
||||
if (!g_csi_info_queue || xQueueSend(g_csi_info_queue, &q_data, 0) == pdFALSE) {
|
||||
ESP_LOGW(TAG, "g_csi_info_queue full");
|
||||
free(q_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void collect_timercb(TimerHandle_t timer)
|
||||
{
|
||||
g_console_input_config.collect_number--;
|
||||
|
||||
if (!g_console_input_config.collect_number) {
|
||||
xTimerStop(g_collect_timer_handele, 0);
|
||||
xTimerDelete(g_collect_timer_handele, 0);
|
||||
g_collect_timer_handele = NULL;
|
||||
strcpy(g_console_input_config.collect_taget, "unknown");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static int wifi_cmd_radar(int argc, char **argv)
|
||||
{
|
||||
if (arg_parse(argc, argv, (void **) &radar_args) != ESP_OK) {
|
||||
arg_print_errors(stderr, radar_args.end, argv[0]);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (radar_args.train_start->count) {
|
||||
if (!radar_args.train_add->count) {
|
||||
esp_radar_train_remove();
|
||||
}
|
||||
|
||||
esp_radar_train_start();
|
||||
g_console_input_config.train_start = true;
|
||||
}
|
||||
|
||||
if (radar_args.train_stop->count) {
|
||||
esp_radar_train_stop(&g_console_input_config.predict_someone_threshold,
|
||||
&g_console_input_config.predict_move_threshold);
|
||||
g_console_input_config.train_start = false;
|
||||
|
||||
printf("RADAR_DADA,0,0,0,%.6f,0,0,%.6f,0\n",
|
||||
g_console_input_config.predict_someone_threshold,
|
||||
g_console_input_config.predict_move_threshold);
|
||||
}
|
||||
|
||||
if (radar_args.predict_move_threshold->count) {
|
||||
g_console_input_config.predict_move_threshold = atof(radar_args.predict_move_threshold->sval[0]);
|
||||
}
|
||||
|
||||
if (radar_args.predict_move_sensitivity->count) {
|
||||
g_console_input_config.predict_move_sensitivity = atof(radar_args.predict_move_sensitivity->sval[0]);
|
||||
ESP_LOGI(TAG, "predict_move_sensitivity: %f", g_console_input_config.predict_move_sensitivity);
|
||||
}
|
||||
|
||||
if (radar_args.predict_someone_threshold->count) {
|
||||
g_console_input_config.predict_someone_threshold = atof(radar_args.predict_someone_threshold->sval[0]);
|
||||
}
|
||||
|
||||
if (radar_args.predict_someone_sensitivity->count) {
|
||||
g_console_input_config.predict_someone_sensitivity = atof(radar_args.predict_someone_sensitivity->sval[0]);
|
||||
ESP_LOGI(TAG, "predict_someone_sensitivity: %f", g_console_input_config.predict_someone_sensitivity);
|
||||
}
|
||||
|
||||
if (radar_args.predict_buff_size->count) {
|
||||
g_console_input_config.predict_buff_size = radar_args.predict_buff_size->ival[0];
|
||||
}
|
||||
|
||||
if (radar_args.predict_outliers_number->count) {
|
||||
g_console_input_config.predict_outliers_number = radar_args.predict_outliers_number->ival[0];
|
||||
}
|
||||
|
||||
if (radar_args.collect_taget->count && radar_args.collect_number->count && radar_args.collect_duration->count) {
|
||||
g_console_input_config.collect_number = radar_args.collect_number->ival[0];
|
||||
strcpy(g_console_input_config.collect_taget, radar_args.collect_taget->sval[0]);
|
||||
|
||||
if (g_collect_timer_handele) {
|
||||
xTimerStop(g_collect_timer_handele, portMAX_DELAY);
|
||||
xTimerDelete(g_collect_timer_handele, portMAX_DELAY);
|
||||
}
|
||||
|
||||
g_collect_timer_handele = xTimerCreate("collect", pdMS_TO_TICKS(radar_args.collect_duration->ival[0]),
|
||||
true, NULL, collect_timercb);
|
||||
xTimerStart(g_collect_timer_handele, portMAX_DELAY);
|
||||
}
|
||||
|
||||
if (radar_args.csi_output_format->count) {
|
||||
strcpy(g_console_input_config.csi_output_format, radar_args.csi_output_format->sval[0]);
|
||||
}
|
||||
|
||||
if (radar_args.csi_output_type->count) {
|
||||
esp_radar_config_t radar_config = {0};
|
||||
esp_radar_get_config(&radar_config);
|
||||
|
||||
if (!strcasecmp(radar_args.csi_output_type->sval[0], "NULL")) {
|
||||
radar_config.csi_config.csi_filtered_cb = NULL;
|
||||
} else {
|
||||
radar_config.csi_config.csi_filtered_cb = wifi_csi_raw_cb;
|
||||
strcpy(g_console_input_config.csi_output_type, radar_args.csi_output_type->sval[0]);
|
||||
#if CONFIG_IDF_TARGET_ESP32C5 || CONFIG_IDF_TARGET_ESP32C61
|
||||
if (!strcasecmp(radar_args.csi_output_type->sval[0], "LLTF")) {
|
||||
radar_config.csi_config.acquire_csi_lltf = true;
|
||||
radar_config.dec_config.ltf_type = RADAR_LTF_TYPE_LLTF;
|
||||
radar_config.dec_config.sub_carrier_step_size = 2;
|
||||
} else if (!strcasecmp(radar_args.csi_output_type->sval[0], "HT-LTF")) {
|
||||
radar_config.csi_config.acquire_csi_lltf = false;
|
||||
radar_config.csi_config.acquire_csi_ht20 = true;
|
||||
radar_config.csi_config.acquire_csi_ht40 = true;
|
||||
radar_config.csi_config.acquire_csi_vht = true;
|
||||
radar_config.dec_config.ltf_type = RADAR_LTF_TYPE_HTLTF;
|
||||
radar_config.dec_config.sub_carrier_step_size = 5;
|
||||
} else if (!strcasecmp(radar_args.csi_output_type->sval[0], "STBC-HT-LTF")) {
|
||||
radar_config.csi_config.acquire_csi_lltf = false;
|
||||
radar_config.csi_config.acquire_csi_ht20 = true;
|
||||
radar_config.csi_config.acquire_csi_ht40 = true;
|
||||
radar_config.csi_config.acquire_csi_vht = true;
|
||||
radar_config.dec_config.ltf_type = RADAR_LTF_TYPE_STBC_HTLTF;
|
||||
radar_config.dec_config.sub_carrier_step_size = 5;
|
||||
} else if (!strcasecmp(radar_args.csi_output_type->sval[0], "HE-LTF")) {
|
||||
radar_config.csi_config.acquire_csi_lltf = false;
|
||||
radar_config.csi_config.acquire_csi_su = true;
|
||||
radar_config.csi_config.acquire_csi_mu = true;
|
||||
radar_config.csi_config.acquire_csi_dcm = true;
|
||||
radar_config.csi_config.acquire_csi_beamformed = true;
|
||||
radar_config.csi_config.acquire_csi_vht = true;
|
||||
radar_config.dec_config.ltf_type = RADAR_LTF_TYPE_HELTF;
|
||||
radar_config.dec_config.sub_carrier_step_size = 5;
|
||||
} else if (!strcasecmp(radar_args.csi_output_type->sval[0], "STBC-HE-LTF")) {
|
||||
radar_config.csi_config.acquire_csi_lltf = false;
|
||||
radar_config.csi_config.acquire_csi_su = true;
|
||||
radar_config.csi_config.acquire_csi_mu = true;
|
||||
radar_config.csi_config.acquire_csi_dcm = true;
|
||||
radar_config.csi_config.acquire_csi_beamformed = true;
|
||||
radar_config.csi_config.acquire_csi_he_stbc_mode = CSI_HE_STBC_MODE_AVERAGE;
|
||||
radar_config.csi_config.acquire_csi_vht = true;
|
||||
radar_config.dec_config.ltf_type = RADAR_LTF_TYPE_STBC_HELTF;
|
||||
radar_config.dec_config.sub_carrier_step_size = 5;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
esp_radar_change_config(&radar_config);
|
||||
}
|
||||
|
||||
if (radar_args.csi_start->count) {
|
||||
esp_radar_start();
|
||||
}
|
||||
|
||||
if (radar_args.csi_stop->count) {
|
||||
esp_radar_stop();
|
||||
}
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32
|
||||
if (radar_args.csi_scale_shift->count) {
|
||||
esp_radar_config_t radar_config = {0};
|
||||
esp_radar_get_config(&radar_config);
|
||||
radar_config.csi_config.shift = radar_args.csi_scale_shift->ival[0];
|
||||
esp_radar_change_config(&radar_config);
|
||||
|
||||
ESP_LOGI(TAG, "manually left shift %d bits of the scale of the CSI data", radar_config.csi_config.shift);
|
||||
}
|
||||
|
||||
if (radar_args.channel_filter->count) {
|
||||
esp_radar_config_t radar_config = {0};
|
||||
esp_radar_get_config(&radar_config);
|
||||
radar_config.csi_config.channel_filter_en = radar_args.channel_filter->ival[0];
|
||||
esp_radar_change_config(&radar_config);
|
||||
|
||||
ESP_LOGI(TAG, "enable(%d) to turn on channel filter to smooth adjacent sub-carrier", radar_config.csi_config.channel_filter_en);
|
||||
}
|
||||
#endif
|
||||
if (radar_args.send_data_interval->count) {
|
||||
g_send_data_interval = radar_args.send_data_interval->ival[0];
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void cmd_register_radar(void)
|
||||
{
|
||||
radar_args.train_start = arg_lit0(NULL, "train_start", "Start calibrating the 'Radar' algorithm");
|
||||
radar_args.train_stop = arg_lit0(NULL, "train_stop", "Stop calibrating the 'Radar' algorithm");
|
||||
radar_args.train_add = arg_lit0(NULL, "train_add", "Calibrate on the basis of saving the calibration results");
|
||||
|
||||
radar_args.predict_someone_threshold = arg_str0(NULL, "predict_someone_threshold", "<0 ~ 1.0>", "Configure the threshold for someone");
|
||||
radar_args.predict_someone_sensitivity = arg_str0(NULL, "predict_someone_sensitivity", "<0 ~ 1.0>", "Configure the sensitivity for someone");
|
||||
radar_args.predict_move_threshold = arg_str0(NULL, "predict_move_threshold", "<0 ~ 1.0>", "Configure the threshold for move");
|
||||
radar_args.predict_move_sensitivity = arg_str0(NULL, "predict_move_sensitivity", "<0 ~ 1.0>", "Configure the sensitivity for move");
|
||||
radar_args.predict_buff_size = arg_int0(NULL, "predict_buff_size", "1 ~ 100", "Buffer size for filtering outliers");
|
||||
radar_args.predict_outliers_number = arg_int0(NULL, "predict_outliers_number", "<1 ~ 100>", "The number of items in the buffer queue greater than the threshold");
|
||||
|
||||
radar_args.collect_taget = arg_str0(NULL, "collect_tagets", "<0 ~ 20>", "Type of CSI data collected");
|
||||
radar_args.collect_number = arg_int0(NULL, "collect_number", "sequence", "Number of times CSI data was collected");
|
||||
radar_args.collect_duration = arg_int0(NULL, "collect_duration", "duration", "Time taken to acquire one CSI data");
|
||||
|
||||
radar_args.csi_start = arg_lit0(NULL, "csi_start", "Start collecting CSI data from Wi-Fi");
|
||||
radar_args.csi_stop = arg_lit0(NULL, "csi_stop", "Stop CSI data collection from Wi-Fi");
|
||||
radar_args.csi_output_type = arg_str0(NULL, "csi_output_type", "<NULL, LLTF, HT-LTF, HE-LTF, STBC-HT-LTF, STBC-HE-LTF>", "Type of CSI data");
|
||||
radar_args.csi_output_format = arg_str0(NULL, "csi_output_format", "<decimal, base64>", "Format of CSI data");
|
||||
radar_args.csi_scale_shift = arg_int0(NULL, "scale_shift", "<0~15>", "manually left shift bits of the scale of the CSI data");
|
||||
radar_args.channel_filter = arg_int0(NULL, "channel_filter", "<0 or 1>", "enable to turn on channel filter to smooth adjacent sub-carrier");
|
||||
|
||||
radar_args.send_data_interval = arg_int0(NULL, "send_data_interval", "<interval_ms>", "The interval between sending null data or ping packets to the router");
|
||||
|
||||
radar_args.end = arg_end(8);
|
||||
|
||||
const esp_console_cmd_t radar_cmd = {
|
||||
.command = "radar",
|
||||
.help = "Radar config",
|
||||
.hint = NULL,
|
||||
.func = &wifi_cmd_radar,
|
||||
.argtable = &radar_args
|
||||
};
|
||||
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&radar_cmd));
|
||||
}
|
||||
|
||||
static void csi_data_print_task(void *arg)
|
||||
{
|
||||
wifi_csi_filtered_info_t *info = NULL;
|
||||
char *buffer = malloc(8 * 1024);
|
||||
static uint32_t count = 0;
|
||||
|
||||
while (xQueueReceive(g_csi_info_queue, &info, portMAX_DELAY)) {
|
||||
size_t len = 0;
|
||||
esp_radar_rx_ctrl_info_t *rx_ctrl = &info->rx_ctrl_info;
|
||||
|
||||
if (!count) {
|
||||
ESP_LOGI(TAG, "================ CSI RECV ================");
|
||||
len += sprintf(buffer + len, "type,sequence,timestamp,taget_seq,target,mac,rssi,rate,sig_mode,mcs,bandwidth,smoothing,not_sounding,aggregation,stbc,fec_coding,sgi,noise_floor,ampdu_cnt,channel,secondary_channel,local_timestamp,ant,sig_len,rx_state,agc_gain,fft_gain,len,first_word,data\n");
|
||||
}
|
||||
uint16_t valid_len = info->valid_len;
|
||||
ESP_LOGI(TAG, "info->valid_len1: %d", info->valid_len);
|
||||
if (!strcasecmp(g_console_input_config.csi_output_type, "LLTF")) {
|
||||
info->valid_len = info->valid_lltf_len;
|
||||
} else if (!strcasecmp(g_console_input_config.csi_output_type, "HT-LTF")) {
|
||||
info->valid_len = info->valid_lltf_len + info->valid_ht_ltf_len;
|
||||
} else if (!strcasecmp(g_console_input_config.csi_output_type, "STBC-HT-LTF")) {
|
||||
info->valid_len = info->valid_lltf_len + info->valid_ht_ltf_len + info->valid_stbc_ht_ltf_len;
|
||||
#if CONFIG_IDF_TARGET_ESP32C5 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32C61
|
||||
} else if (!strcasecmp(g_console_input_config.csi_output_type, "HE-LTF")) {
|
||||
info->valid_len = info->valid_he_ltf_len;
|
||||
} else if (!strcasecmp(g_console_input_config.csi_output_type, "STBC-HE-LTF")) {
|
||||
info->valid_len = info->valid_he_ltf_len + info->valid_stbc_he_ltf_len;
|
||||
#endif
|
||||
}
|
||||
ESP_LOGI(TAG, "info->valid_len: %d", info->valid_len);
|
||||
if (info->valid_len == 0) {
|
||||
info->valid_len = valid_len;
|
||||
|
||||
}
|
||||
len += sprintf(buffer + len, "CSI_DATA,%s,%s,%d,%u,%u,%s," MACSTR ",%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%u,%d,%d,%d,%d,%d,%d,%d,",
|
||||
CONFIG_DEVICE_NAME, CONFIG_DEVICE_LOCATION,
|
||||
count++, esp_log_timestamp(), g_console_input_config.collect_number, g_console_input_config.collect_taget,
|
||||
MAC2STR(info->mac), rx_ctrl->rssi, rx_ctrl->rate, rx_ctrl->signal_mode,
|
||||
rx_ctrl->mcs, rx_ctrl->cwb, 0, 0,
|
||||
0, rx_ctrl->stbc, 0, 0,
|
||||
rx_ctrl->noise_floor, 0, rx_ctrl->channel, rx_ctrl->secondary_channel,
|
||||
rx_ctrl->timestamp, 0, 0, 0, rx_ctrl->agc_gain, rx_ctrl->fft_gain, info->valid_len, 0);
|
||||
|
||||
if (!strcasecmp(g_console_input_config.csi_output_format, "base64")) {
|
||||
size_t size = 0;
|
||||
mbedtls_base64_encode((uint8_t *)buffer + len, sizeof(buffer) - len, &size, (uint8_t *)info->valid_data, info->valid_len);
|
||||
len += size;
|
||||
len += sprintf(buffer + len, "\n");
|
||||
} else {
|
||||
len += sprintf(buffer + len, "\"[%d", info->valid_data[0]);
|
||||
|
||||
for (int i = 1; i < info->valid_len; i++) {
|
||||
len += sprintf(buffer + len, ",%d", info->valid_data[i]);
|
||||
}
|
||||
|
||||
len += sprintf(buffer + len, "]\"\n");
|
||||
}
|
||||
|
||||
printf("%s", buffer);
|
||||
free(info);
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
static void wifi_radar_cb(void *ctx, const wifi_radar_info_t *info)
|
||||
{
|
||||
static float *s_buff_wander = NULL;
|
||||
static float *s_buff_jitter = NULL;
|
||||
static uint32_t s_buff_count = 0;
|
||||
uint32_t buff_max_size = g_console_input_config.predict_buff_size;
|
||||
uint32_t buff_outliers_num = g_console_input_config.predict_outliers_number;
|
||||
uint32_t someone_count = 0;
|
||||
uint32_t move_count = 0;
|
||||
bool room_status = false;
|
||||
bool human_status = false;
|
||||
|
||||
if (!s_buff_wander) {
|
||||
s_buff_wander = calloc(RADAR_BUFF_MAX_LEN, sizeof(float));
|
||||
}
|
||||
|
||||
if (!s_buff_jitter) {
|
||||
s_buff_jitter = calloc(RADAR_BUFF_MAX_LEN, sizeof(float));
|
||||
}
|
||||
|
||||
s_buff_wander[s_buff_count % RADAR_BUFF_MAX_LEN] = info->waveform_wander;
|
||||
s_buff_jitter[s_buff_count % RADAR_BUFF_MAX_LEN] = info->waveform_jitter;
|
||||
s_buff_count++;
|
||||
|
||||
if (s_buff_count < buff_max_size) {
|
||||
return;
|
||||
}
|
||||
|
||||
extern float trimmean(const float * array, size_t len, float percent);
|
||||
extern float median(const float * a, size_t len);
|
||||
|
||||
float wander_average = trimmean(s_buff_wander, RADAR_BUFF_MAX_LEN, 0.5);
|
||||
float jitter_midean = median(s_buff_jitter, RADAR_BUFF_MAX_LEN);
|
||||
|
||||
for (int i = 0; i < buff_max_size; i++) {
|
||||
uint32_t index = (s_buff_count - 1 - i) % RADAR_BUFF_MAX_LEN;
|
||||
|
||||
if ((wander_average * g_console_input_config.predict_someone_sensitivity > g_console_input_config.predict_someone_threshold)) {
|
||||
someone_count++;
|
||||
}
|
||||
|
||||
if (s_buff_jitter[index] * g_console_input_config.predict_move_sensitivity > g_console_input_config.predict_move_threshold
|
||||
|| (s_buff_jitter[index] * g_console_input_config.predict_move_sensitivity > jitter_midean && s_buff_jitter[index] > 0.0002)) {
|
||||
move_count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (someone_count >= 1) {
|
||||
room_status = true;
|
||||
}
|
||||
|
||||
if (move_count >= buff_outliers_num) {
|
||||
human_status = true;
|
||||
}
|
||||
|
||||
static uint32_t s_count = 0;
|
||||
|
||||
if (!s_count) {
|
||||
ESP_LOGI(TAG, "================ RADAR RECV ================");
|
||||
ESP_LOGI(TAG, "type,sequence,timestamp,waveform_wander,someone_threshold,someone_status,waveform_jitter,move_threshold,move_status");
|
||||
}
|
||||
|
||||
char timestamp_str[32] = {0};
|
||||
sprintf(timestamp_str, "%u", esp_log_timestamp());
|
||||
|
||||
if (ctx) {
|
||||
strncpy(timestamp_str, (char *)ctx, 31);
|
||||
}
|
||||
|
||||
static uint32_t s_last_move_time = 0;
|
||||
static uint32_t s_last_someone_time = 0;
|
||||
|
||||
if (g_console_input_config.train_start) {
|
||||
s_last_move_time = esp_log_timestamp();
|
||||
s_last_someone_time = esp_log_timestamp();
|
||||
|
||||
static bool led_status = false;
|
||||
|
||||
if (led_status) {
|
||||
led_strip_set_pixel(led_strip, 0, 0, 0, 0);
|
||||
} else {
|
||||
led_strip_set_pixel(led_strip, 0, 255, 255, 0);
|
||||
}
|
||||
led_status = !led_status;
|
||||
led_strip_refresh(led_strip);
|
||||
return;
|
||||
}
|
||||
|
||||
printf("RADAR_DADA,%d,%s,%.6f,%.6f,%.6f,%d,%.6f,%.6f,%.6f,%d\n",
|
||||
s_count++, timestamp_str,
|
||||
info->waveform_wander, wander_average, g_console_input_config.predict_someone_threshold / g_console_input_config.predict_someone_sensitivity, room_status,
|
||||
info->waveform_jitter, jitter_midean, jitter_midean / g_console_input_config.predict_move_sensitivity, human_status);
|
||||
|
||||
if (room_status) {
|
||||
if (human_status) {
|
||||
led_strip_set_pixel(led_strip, 0, 0, 255, 0);
|
||||
ESP_LOGI(TAG, "Someone moved");
|
||||
s_last_move_time = esp_log_timestamp();
|
||||
} else if (esp_log_timestamp() - s_last_move_time > 3 * 1000) {
|
||||
led_strip_set_pixel(led_strip, 0, 255, 255, 255);
|
||||
ESP_LOGI(TAG, "Someone");
|
||||
}
|
||||
|
||||
s_last_someone_time = esp_log_timestamp();
|
||||
} else if (esp_log_timestamp() - s_last_someone_time > 3 * 1000) {
|
||||
if (human_status) {
|
||||
s_last_move_time = esp_log_timestamp();
|
||||
led_strip_set_pixel(led_strip, 0, 255, 0, 0);
|
||||
} else if (esp_log_timestamp() - s_last_move_time > 3 * 1000) {
|
||||
led_strip_set_pixel(led_strip, 0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
led_strip_refresh(led_strip);
|
||||
}
|
||||
|
||||
static void trigger_router_send_data_task(void *arg)
|
||||
{
|
||||
esp_radar_config_t radar_config = {0};
|
||||
wifi_ap_record_t ap_info = {0};
|
||||
uint8_t sta_mac[6] = {0};
|
||||
|
||||
esp_radar_get_config(&radar_config);
|
||||
esp_wifi_sta_get_ap_info(&ap_info);
|
||||
ESP_ERROR_CHECK(esp_wifi_get_mac(WIFI_IF_STA, sta_mac));
|
||||
|
||||
radar_config.csi_config.csi_recv_interval = g_send_data_interval;
|
||||
memcpy(radar_config.csi_config.filter_dmac, sta_mac, sizeof(radar_config.csi_config.filter_dmac));
|
||||
|
||||
#if WIFI_CSI_SEND_NULL_DATA_ENABLE
|
||||
ESP_LOGI(TAG, "Send null data to router");
|
||||
|
||||
memset(radar_config.csi_config.filter_mac, 0, sizeof(radar_config.csi_config.filter_mac));
|
||||
esp_radar_change_config(&radar_config);
|
||||
|
||||
typedef struct {
|
||||
uint8_t frame_control[2];
|
||||
uint16_t duration;
|
||||
uint8_t destination_address[6];
|
||||
uint8_t source_address[6];
|
||||
uint8_t broadcast_address[6];
|
||||
uint16_t sequence_control;
|
||||
} __attribute__((packed)) wifi_null_data_t;
|
||||
|
||||
wifi_null_data_t null_data = {
|
||||
.frame_control = {0x48, 0x01},
|
||||
.duration = 0x0000,
|
||||
.sequence_control = 0x0000,
|
||||
};
|
||||
|
||||
memcpy(null_data.destination_address, ap_info.bssid, 6);
|
||||
memcpy(null_data.broadcast_address, ap_info.bssid, 6);
|
||||
memcpy(null_data.source_address, sta_mac, 6);
|
||||
|
||||
ESP_LOGW(TAG, "null_data, destination_address: "MACSTR", source_address: "MACSTR", broadcast_address: " MACSTR,
|
||||
MAC2STR(null_data.destination_address), MAC2STR(null_data.source_address), MAC2STR(null_data.broadcast_address));
|
||||
|
||||
ESP_ERROR_CHECK(esp_wifi_config_80211_tx_rate(WIFI_IF_STA, WIFI_PHY_RATE_6M));
|
||||
|
||||
for (int i = 0; g_wifi_connect_status; i++) {
|
||||
esp_err_t ret = esp_wifi_80211_tx(WIFI_IF_STA, &null_data, sizeof(wifi_null_data_t), true);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGW(TAG, "esp_wifi_80211_tx, %s", esp_err_to_name(ret));
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
}
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(g_send_data_interval));
|
||||
}
|
||||
|
||||
#else
|
||||
ESP_LOGI(TAG, "Send ping data to router");
|
||||
|
||||
memcpy(radar_config.csi_config.filter_mac, ap_info.bssid, sizeof(radar_config.csi_config.filter_mac));
|
||||
esp_radar_change_config(&radar_config);
|
||||
|
||||
/* stop and delete existing ping session if any */
|
||||
if (g_ping_handle != NULL) {
|
||||
ESP_LOGI(TAG, "Stopping existing ping session before starting new one");
|
||||
esp_ping_stop(g_ping_handle);
|
||||
esp_ping_delete_session(g_ping_handle);
|
||||
g_ping_handle = NULL;
|
||||
ESP_LOGI(TAG, "Existing ping session stopped and deleted");
|
||||
}
|
||||
|
||||
esp_ping_config_t config = ESP_PING_DEFAULT_CONFIG();
|
||||
config.count = 0;
|
||||
config.data_size = 1;
|
||||
config.interval_ms = g_send_data_interval;
|
||||
|
||||
/**
|
||||
* @brief Get the Router IP information from the esp-netif
|
||||
*/
|
||||
esp_netif_ip_info_t local_ip;
|
||||
esp_netif_get_ip_info(esp_netif_get_handle_from_ifkey("WIFI_STA_DEF"), &local_ip);
|
||||
ESP_LOGI(TAG, "Ping: got ip:" IPSTR ", gw: " IPSTR, IP2STR(&local_ip.ip), IP2STR(&local_ip.gw));
|
||||
config.target_addr.u_addr.ip4.addr = ip4_addr_get_u32(&local_ip.gw);
|
||||
config.target_addr.type = ESP_IPADDR_TYPE_V4;
|
||||
|
||||
esp_ping_callbacks_t cbs = { 0 };
|
||||
esp_ping_new_session(&config, &cbs, &g_ping_handle);
|
||||
esp_ping_start(g_ping_handle);
|
||||
#endif
|
||||
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
/* Event handler for catching system events */
|
||||
static void wifi_event_handler(void *arg, esp_event_base_t event_base,
|
||||
int32_t event_id, void *event_data)
|
||||
{
|
||||
if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
|
||||
g_wifi_connect_status = true;
|
||||
|
||||
xTaskCreate(trigger_router_send_data_task, "trigger_router_send_data", 4 * 1024, NULL, 5, NULL);
|
||||
|
||||
#ifdef RECV_ESPNOW_CSI
|
||||
ESP_ERROR_CHECK(esp_wifi_set_promiscuous(false));
|
||||
#endif
|
||||
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
|
||||
g_wifi_connect_status = false;
|
||||
ESP_LOGW(TAG, "Wi-Fi disconnected");
|
||||
esp_radar_config_t radar_config;
|
||||
esp_radar_get_config(&radar_config);
|
||||
esp_radar_wifi_reinit(&radar_config.wifi_config);
|
||||
|
||||
}
|
||||
}
|
||||
esp_err_t ws2812_led_init(void)
|
||||
{
|
||||
led_strip_config_t strip_config = {
|
||||
.strip_gpio_num = WS2812_GPIO,
|
||||
.max_leds = 1,
|
||||
};
|
||||
|
||||
led_strip_rmt_config_t rmt_config = {
|
||||
.clk_src = RMT_CLK_SRC_DEFAULT, // different clock source can lead to different power consumption
|
||||
.resolution_hz = 10 * 1000 * 1000, // RMT counter clock frequency: 10MHz
|
||||
.flags = {
|
||||
.with_dma = false, // DMA feature is available on chips like ESP32-S3/P4
|
||||
}
|
||||
};
|
||||
ESP_ERROR_CHECK(led_strip_new_rmt_device(&strip_config, &rmt_config, &led_strip));
|
||||
/* Set all LED off to clear all pixels */
|
||||
led_strip_clear(led_strip);
|
||||
return ESP_OK;
|
||||
}
|
||||
void app_main(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "app_main start, line: %d", __LINE__);
|
||||
/**
|
||||
* @brief Initialize NVS
|
||||
*/
|
||||
|
||||
esp_err_t ret = nvs_flash_init();
|
||||
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
||||
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||
ret = nvs_flash_init();
|
||||
}
|
||||
ESP_ERROR_CHECK(ret);
|
||||
ESP_LOGI(TAG, "app_main line: %d", __LINE__);
|
||||
/**
|
||||
* @brief Install ws2812 driver, Used to display the status of the device
|
||||
*/
|
||||
ws2812_led_init();
|
||||
|
||||
ESP_LOGI(TAG, "app_main start, line: %d", __LINE__);
|
||||
/**
|
||||
* @brief Turn on the radar module printing information
|
||||
*/
|
||||
esp_log_level_set("esp_radar", ESP_LOG_INFO);
|
||||
|
||||
/**
|
||||
* @brief Register serial command
|
||||
*/
|
||||
esp_console_repl_t *repl = NULL;
|
||||
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT();
|
||||
esp_console_dev_uart_config_t uart_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT();
|
||||
repl_config.prompt = "csi>";
|
||||
ESP_ERROR_CHECK(esp_console_new_repl_uart(&uart_config, &repl_config, &repl));
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
|
||||
/**< Fix serial port garbled code due to high baud rate */
|
||||
uart_ll_set_sclk(UART_LL_GET_HW(CONFIG_ESP_CONSOLE_UART_NUM), UART_SCLK_APB);
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||
uart_ll_set_baudrate(UART_LL_GET_HW(CONFIG_ESP_CONSOLE_UART_NUM), CONFIG_ESP_CONSOLE_UART_BAUDRATE, APB_CLK_FREQ);
|
||||
#else
|
||||
uart_ll_set_baudrate(UART_LL_GET_HW(CONFIG_ESP_CONSOLE_UART_NUM), CONFIG_ESP_CONSOLE_UART_BAUDRATE);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Set the Wi-Fi radar configuration
|
||||
*/
|
||||
esp_radar_csi_config_t csi_config = ESP_RADAR_CSI_CONFIG_DEFAULT();
|
||||
esp_radar_wifi_config_t wifi_config = ESP_RADAR_WIFI_CONFIG_DEFAULT();
|
||||
esp_radar_espnow_config_t espnow_config = ESP_RADAR_ESPNOW_CONFIG_DEFAULT();
|
||||
esp_radar_dec_config_t dec_config = ESP_RADAR_DEC_CONFIG_DEFAULT();
|
||||
memcpy(csi_config.filter_mac, "\x1a\x00\x00\x00\x00\x00", 6);
|
||||
csi_config.csi_recv_interval = g_send_data_interval;
|
||||
dec_config.wifi_radar_cb = wifi_radar_cb;
|
||||
#if WIFI_CSI_SEND_NULL_DATA_ENABLE
|
||||
csi_config.dump_ack_en = true;
|
||||
#endif
|
||||
dec_config.outliers_threshold = 0;
|
||||
ESP_ERROR_CHECK(esp_radar_wifi_init(&wifi_config));
|
||||
ESP_ERROR_CHECK(esp_radar_csi_init(&csi_config));
|
||||
ESP_ERROR_CHECK(esp_radar_dec_init(&dec_config));
|
||||
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &wifi_event_handler, NULL));
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &wifi_event_handler, NULL));
|
||||
|
||||
cmd_register_ping();
|
||||
cmd_register_system();
|
||||
cmd_register_wifi_config();
|
||||
cmd_register_wifi_scan();
|
||||
cmd_register_radar();
|
||||
ESP_ERROR_CHECK(esp_console_start_repl(repl));
|
||||
|
||||
/**
|
||||
* @brief Start Wi-Fi radar
|
||||
*/
|
||||
esp_radar_start();
|
||||
|
||||
/**
|
||||
* @brief Initialize CSI serial port printing task, Use tasks to avoid blocking wifi_csi_raw_cb
|
||||
*/
|
||||
g_csi_info_queue = xQueueCreate(64, sizeof(void *));
|
||||
xTaskCreate(csi_data_print_task, "csi_data_print", 4 * 1024, NULL, 0, NULL);
|
||||
}
|
||||
7
esp-radar/console_test/main/idf_component.yml
Normal file
7
esp-radar/console_test/main/idf_component.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
## IDF Component Manager Manifest File
|
||||
dependencies:
|
||||
idf: ">=4.4.1"
|
||||
|
||||
esp-radar: ">=0.3.0"
|
||||
|
||||
espressif/led_strip: "^2.5.3"
|
||||
255
esp-radar/console_test/main/radar_evaluate.c
Normal file
255
esp-radar/console_test/main/radar_evaluate.c
Normal file
@@ -0,0 +1,255 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
8
esp-radar/console_test/partitions.csv
Normal file
8
esp-radar/console_test/partitions.csv
Normal file
@@ -0,0 +1,8 @@
|
||||
# Note: Firmware partition offset needs to be 64K aligned, initial 36K (9 sectors) are reserved for bootloader and partition table
|
||||
# Name, Type, SubType, Offset, Size, Flags
|
||||
nvs, data, nvs, 0xd000, 32K,
|
||||
fctry, data, nvs, 0x15000, 16K,
|
||||
log_status, data, nvs, 0x19000, 16K,
|
||||
otadata, data, ota, 0x1d000, 8K,
|
||||
phy_init, data, phy, 0x1f000, 4K,
|
||||
ota_0, app, ota_0, 0x20000, 1832K,
|
||||
|
53
esp-radar/console_test/sdkconfig.defaults
Normal file
53
esp-radar/console_test/sdkconfig.defaults
Normal file
@@ -0,0 +1,53 @@
|
||||
#
|
||||
# Serial flasher config
|
||||
#
|
||||
CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
|
||||
CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
|
||||
CONFIG_ESPTOOLPY_BAUD_921600B=y
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
|
||||
CONFIG_ESPTOOLPY_MONITOR_BAUD_2MB=y
|
||||
CONFIG_ESP_CONSOLE_UART_BAUDRATE=2000000
|
||||
|
||||
#
|
||||
# Partition Table
|
||||
#
|
||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
||||
|
||||
#
|
||||
# Wi-Fi
|
||||
#
|
||||
CONFIG_ESP32_WIFI_CSI_ENABLED=y
|
||||
CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=
|
||||
|
||||
#
|
||||
# Common ESP-related
|
||||
#
|
||||
CONFIG_ESP_CONSOLE_UART_CUSTOM=y
|
||||
CONFIG_ESP_CONSOLE_UART=y
|
||||
CONFIG_ESP_CONSOLE_UART_NUM=0
|
||||
CONFIG_ESP_TASK_WDT_TIMEOUT_S=30
|
||||
|
||||
#
|
||||
# Compiler options
|
||||
#
|
||||
CONFIG_COMPILER_OPTIMIZATION_PERF=y
|
||||
|
||||
#
|
||||
# FreeRTOS
|
||||
#
|
||||
CONFIG_FREERTOS_HZ=1000
|
||||
|
||||
#
|
||||
# ESP32-specific
|
||||
#
|
||||
CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y
|
||||
CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240
|
||||
|
||||
CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=32
|
||||
|
||||
#
|
||||
# ESP32S3-specific
|
||||
#
|
||||
CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240=y
|
||||
CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ=240
|
||||
1
esp-radar/console_test/tools/config/gui_config.json
Normal file
1
esp-radar/console_test/tools/config/gui_config.json
Normal file
@@ -0,0 +1 @@
|
||||
{"router_ssid": "Tplink_nyx", "router_password": "12345678", "router_auto_connect": false, "display_raw_data": true, "display_radar_model": true, "display_eigenvalues_table": false}
|
||||
1335
esp-radar/console_test/tools/esp_csi_tool.py
Executable file
1335
esp-radar/console_test/tools/esp_csi_tool.py
Executable file
File diff suppressed because it is too large
Load Diff
869
esp-radar/console_test/tools/esp_csi_tool_gui.py
Normal file
869
esp-radar/console_test/tools/esp_csi_tool_gui.py
Normal file
@@ -0,0 +1,869 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'esp_csi_tool_gui.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.15.10
|
||||
#
|
||||
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
||||
# run again. Do not edit this file unless you know what you are doing.
|
||||
|
||||
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
|
||||
|
||||
class Ui_MainWindow(object):
|
||||
def setupUi(self, MainWindow):
|
||||
MainWindow.setObjectName("MainWindow")
|
||||
MainWindow.resize(1563, 850)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(14)
|
||||
font.setStyleStrategy(QtGui.QFont.PreferAntialias)
|
||||
MainWindow.setFont(font)
|
||||
MainWindow.setDockOptions(QtWidgets.QMainWindow.AllowTabbedDocks|QtWidgets.QMainWindow.AnimatedDocks)
|
||||
self.centralwidget = QtWidgets.QWidget(MainWindow)
|
||||
self.centralwidget.setObjectName("centralwidget")
|
||||
self.verticalLayout_17 = QtWidgets.QVBoxLayout(self.centralwidget)
|
||||
self.verticalLayout_17.setContentsMargins(0, 0, 0, 0)
|
||||
self.verticalLayout_17.setSpacing(0)
|
||||
self.verticalLayout_17.setObjectName("verticalLayout_17")
|
||||
self.horizontalLayout_11 = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout_11.setSizeConstraint(QtWidgets.QLayout.SetMinimumSize)
|
||||
self.horizontalLayout_11.setSpacing(12)
|
||||
self.horizontalLayout_11.setObjectName("horizontalLayout_11")
|
||||
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
||||
self.horizontalLayout_11.addItem(spacerItem)
|
||||
self.label_2 = QtWidgets.QLabel(self.centralwidget)
|
||||
self.label_2.setObjectName("label_2")
|
||||
self.horizontalLayout_11.addWidget(self.label_2)
|
||||
self.checkBox_raw_data = QtWidgets.QCheckBox(self.centralwidget)
|
||||
self.checkBox_raw_data.setChecked(True)
|
||||
self.checkBox_raw_data.setObjectName("checkBox_raw_data")
|
||||
self.horizontalLayout_11.addWidget(self.checkBox_raw_data)
|
||||
self.checkBox_radar_model = QtWidgets.QCheckBox(self.centralwidget)
|
||||
self.checkBox_radar_model.setChecked(True)
|
||||
self.checkBox_radar_model.setObjectName("checkBox_radar_model")
|
||||
self.horizontalLayout_11.addWidget(self.checkBox_radar_model)
|
||||
self.verticalLayout_17.addLayout(self.horizontalLayout_11)
|
||||
self.splitter_display = QtWidgets.QSplitter(self.centralwidget)
|
||||
self.splitter_display.setOrientation(QtCore.Qt.Horizontal)
|
||||
self.splitter_display.setObjectName("splitter_display")
|
||||
self.groupBox_raw_data = QtWidgets.QGroupBox(self.splitter_display)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(14)
|
||||
font.setBold(True)
|
||||
font.setWeight(75)
|
||||
font.setStyleStrategy(QtGui.QFont.PreferAntialias)
|
||||
self.groupBox_raw_data.setFont(font)
|
||||
self.groupBox_raw_data.setAlignment(QtCore.Qt.AlignCenter)
|
||||
self.groupBox_raw_data.setObjectName("groupBox_raw_data")
|
||||
self.verticalLayout_6 = QtWidgets.QVBoxLayout(self.groupBox_raw_data)
|
||||
self.verticalLayout_6.setContentsMargins(0, 0, 0, 0)
|
||||
self.verticalLayout_6.setSpacing(0)
|
||||
self.verticalLayout_6.setObjectName("verticalLayout_6")
|
||||
self.splitter_raw_data = QtWidgets.QSplitter(self.groupBox_raw_data)
|
||||
self.splitter_raw_data.setOrientation(QtCore.Qt.Vertical)
|
||||
self.splitter_raw_data.setObjectName("splitter_raw_data")
|
||||
self.groupBox_16 = QtWidgets.QGroupBox(self.splitter_raw_data)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.groupBox_16.sizePolicy().hasHeightForWidth())
|
||||
self.groupBox_16.setSizePolicy(sizePolicy)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(10)
|
||||
font.setBold(False)
|
||||
font.setWeight(50)
|
||||
font.setStyleStrategy(QtGui.QFont.PreferAntialias)
|
||||
self.groupBox_16.setFont(font)
|
||||
self.groupBox_16.setObjectName("groupBox_16")
|
||||
self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.groupBox_16)
|
||||
self.verticalLayout_4.setContentsMargins(0, 0, 0, 0)
|
||||
self.verticalLayout_4.setSpacing(0)
|
||||
self.verticalLayout_4.setObjectName("verticalLayout_4")
|
||||
self.groupBox_11 = QtWidgets.QGroupBox(self.groupBox_16)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.groupBox_11.sizePolicy().hasHeightForWidth())
|
||||
self.groupBox_11.setSizePolicy(sizePolicy)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(10)
|
||||
font.setBold(False)
|
||||
font.setWeight(50)
|
||||
font.setStyleStrategy(QtGui.QFont.PreferAntialias)
|
||||
self.groupBox_11.setFont(font)
|
||||
self.groupBox_11.setObjectName("groupBox_11")
|
||||
self.horizontalLayout_13 = QtWidgets.QHBoxLayout(self.groupBox_11)
|
||||
self.horizontalLayout_13.setContentsMargins(0, 0, 0, 0)
|
||||
self.horizontalLayout_13.setSpacing(9)
|
||||
self.horizontalLayout_13.setObjectName("horizontalLayout_13")
|
||||
self.label_delay_2 = QtWidgets.QLabel(self.groupBox_11)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.label_delay_2.sizePolicy().hasHeightForWidth())
|
||||
self.label_delay_2.setSizePolicy(sizePolicy)
|
||||
self.label_delay_2.setObjectName("label_delay_2")
|
||||
self.horizontalLayout_13.addWidget(self.label_delay_2)
|
||||
self.lineEdit_router_ssid = QtWidgets.QLineEdit(self.groupBox_11)
|
||||
self.lineEdit_router_ssid.setObjectName("lineEdit_router_ssid")
|
||||
self.horizontalLayout_13.addWidget(self.lineEdit_router_ssid)
|
||||
self.label_duration_2 = QtWidgets.QLabel(self.groupBox_11)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.label_duration_2.sizePolicy().hasHeightForWidth())
|
||||
self.label_duration_2.setSizePolicy(sizePolicy)
|
||||
self.label_duration_2.setObjectName("label_duration_2")
|
||||
self.horizontalLayout_13.addWidget(self.label_duration_2)
|
||||
self.lineEdit_router_password = QtWidgets.QLineEdit(self.groupBox_11)
|
||||
self.lineEdit_router_password.setObjectName("lineEdit_router_password")
|
||||
self.horizontalLayout_13.addWidget(self.lineEdit_router_password)
|
||||
self.checkBox_router_auto_connect = QtWidgets.QCheckBox(self.groupBox_11)
|
||||
self.checkBox_router_auto_connect.setChecked(True)
|
||||
self.checkBox_router_auto_connect.setObjectName("checkBox_router_auto_connect")
|
||||
self.horizontalLayout_13.addWidget(self.checkBox_router_auto_connect)
|
||||
self.pushButton_router_connect = QtWidgets.QPushButton(self.groupBox_11)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(14)
|
||||
font.setBold(False)
|
||||
font.setWeight(50)
|
||||
font.setStyleStrategy(QtGui.QFont.PreferAntialias)
|
||||
self.pushButton_router_connect.setFont(font)
|
||||
self.pushButton_router_connect.setAutoDefault(False)
|
||||
self.pushButton_router_connect.setDefault(False)
|
||||
self.pushButton_router_connect.setObjectName("pushButton_router_connect")
|
||||
self.horizontalLayout_13.addWidget(self.pushButton_router_connect)
|
||||
self.horizontalLayout_13.setStretch(0, 1)
|
||||
self.horizontalLayout_13.setStretch(1, 4)
|
||||
self.horizontalLayout_13.setStretch(2, 1)
|
||||
self.horizontalLayout_13.setStretch(3, 4)
|
||||
self.horizontalLayout_13.setStretch(4, 1)
|
||||
self.horizontalLayout_13.setStretch(5, 2)
|
||||
self.verticalLayout_4.addWidget(self.groupBox_11)
|
||||
self.horizontalLayout_4 = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout_4.setSpacing(0)
|
||||
self.horizontalLayout_4.setObjectName("horizontalLayout_4")
|
||||
self.label = QtWidgets.QLabel(self.groupBox_16)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(10)
|
||||
font.setBold(False)
|
||||
font.setWeight(50)
|
||||
font.setStyleStrategy(QtGui.QFont.PreferAntialias)
|
||||
self.label.setFont(font)
|
||||
self.label.setObjectName("label")
|
||||
self.horizontalLayout_4.addWidget(self.label)
|
||||
self.lineEdit_command = QtWidgets.QLineEdit(self.groupBox_16)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(10)
|
||||
font.setBold(False)
|
||||
font.setWeight(50)
|
||||
font.setStyleStrategy(QtGui.QFont.PreferAntialias)
|
||||
self.lineEdit_command.setFont(font)
|
||||
self.lineEdit_command.setObjectName("lineEdit_command")
|
||||
self.horizontalLayout_4.addWidget(self.lineEdit_command)
|
||||
self.comboBox_command = QtWidgets.QComboBox(self.groupBox_16)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(10)
|
||||
font.setBold(False)
|
||||
font.setWeight(50)
|
||||
font.setStyleStrategy(QtGui.QFont.PreferAntialias)
|
||||
self.comboBox_command.setFont(font)
|
||||
self.comboBox_command.setObjectName("comboBox_command")
|
||||
self.comboBox_command.addItem("")
|
||||
self.comboBox_command.addItem("")
|
||||
self.comboBox_command.addItem("")
|
||||
self.comboBox_command.addItem("")
|
||||
self.comboBox_command.addItem("")
|
||||
self.comboBox_command.addItem("")
|
||||
self.comboBox_command.addItem("")
|
||||
self.horizontalLayout_4.addWidget(self.comboBox_command)
|
||||
self.pushButton_command = QtWidgets.QPushButton(self.groupBox_16)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(10)
|
||||
font.setBold(False)
|
||||
font.setWeight(50)
|
||||
font.setStyleStrategy(QtGui.QFont.PreferAntialias)
|
||||
self.pushButton_command.setFont(font)
|
||||
self.pushButton_command.setObjectName("pushButton_command")
|
||||
self.horizontalLayout_4.addWidget(self.pushButton_command)
|
||||
self.horizontalLayout_4.setStretch(0, 1)
|
||||
self.horizontalLayout_4.setStretch(1, 8)
|
||||
self.horizontalLayout_4.setStretch(2, 3)
|
||||
self.horizontalLayout_4.setStretch(3, 2)
|
||||
self.verticalLayout_4.addLayout(self.horizontalLayout_4)
|
||||
self.layoutWidget = QtWidgets.QWidget(self.splitter_raw_data)
|
||||
self.layoutWidget.setObjectName("layoutWidget")
|
||||
self.verticalLayout_7 = QtWidgets.QVBoxLayout(self.layoutWidget)
|
||||
self.verticalLayout_7.setContentsMargins(0, 0, 0, 0)
|
||||
self.verticalLayout_7.setSpacing(0)
|
||||
self.verticalLayout_7.setObjectName("verticalLayout_7")
|
||||
self.groupBox_subcarrier = QtWidgets.QGroupBox(self.layoutWidget)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(10)
|
||||
font.setBold(False)
|
||||
font.setWeight(50)
|
||||
font.setStyleStrategy(QtGui.QFont.PreferAntialias)
|
||||
self.groupBox_subcarrier.setFont(font)
|
||||
self.groupBox_subcarrier.setFlat(False)
|
||||
self.groupBox_subcarrier.setCheckable(False)
|
||||
self.groupBox_subcarrier.setObjectName("groupBox_subcarrier")
|
||||
self.verticalLayout_9 = QtWidgets.QVBoxLayout(self.groupBox_subcarrier)
|
||||
self.verticalLayout_9.setContentsMargins(0, 0, 0, 0)
|
||||
self.verticalLayout_9.setSpacing(0)
|
||||
self.verticalLayout_9.setObjectName("verticalLayout_9")
|
||||
self.horizontalLayout_8 = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout_8.setObjectName("horizontalLayout_8")
|
||||
self.verticalLayout_9.addLayout(self.horizontalLayout_8)
|
||||
self.graphicsView_subcarrier = PlotWidget(self.groupBox_subcarrier)
|
||||
self.graphicsView_subcarrier.setObjectName("graphicsView_subcarrier")
|
||||
self.verticalLayout_9.addWidget(self.graphicsView_subcarrier)
|
||||
self.checkBox_wave_filtering = QtWidgets.QCheckBox(self.groupBox_subcarrier)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(10)
|
||||
font.setBold(False)
|
||||
font.setWeight(50)
|
||||
font.setStyleStrategy(QtGui.QFont.PreferAntialias)
|
||||
self.checkBox_wave_filtering.setFont(font)
|
||||
self.checkBox_wave_filtering.setLayoutDirection(QtCore.Qt.LeftToRight)
|
||||
self.checkBox_wave_filtering.setChecked(True)
|
||||
self.checkBox_wave_filtering.setObjectName("checkBox_wave_filtering")
|
||||
self.verticalLayout_9.addWidget(self.checkBox_wave_filtering)
|
||||
self.verticalLayout_7.addWidget(self.groupBox_subcarrier)
|
||||
self.groupBox_rssi = QtWidgets.QGroupBox(self.layoutWidget)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(10)
|
||||
font.setBold(False)
|
||||
font.setWeight(50)
|
||||
font.setStyleStrategy(QtGui.QFont.PreferAntialias)
|
||||
self.groupBox_rssi.setFont(font)
|
||||
self.groupBox_rssi.setObjectName("groupBox_rssi")
|
||||
self.verticalLayout_10 = QtWidgets.QVBoxLayout(self.groupBox_rssi)
|
||||
self.verticalLayout_10.setContentsMargins(0, 0, 0, 0)
|
||||
self.verticalLayout_10.setSpacing(0)
|
||||
self.verticalLayout_10.setObjectName("verticalLayout_10")
|
||||
self.graphicsView_rssi = PlotWidget(self.groupBox_rssi)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.graphicsView_rssi.sizePolicy().hasHeightForWidth())
|
||||
self.graphicsView_rssi.setSizePolicy(sizePolicy)
|
||||
self.graphicsView_rssi.setObjectName("graphicsView_rssi")
|
||||
self.verticalLayout_10.addWidget(self.graphicsView_rssi)
|
||||
self.verticalLayout_7.addWidget(self.groupBox_rssi)
|
||||
self.verticalLayout_7.setStretch(0, 32)
|
||||
self.verticalLayout_7.setStretch(1, 1)
|
||||
self.groupBox_13 = QtWidgets.QGroupBox(self.splitter_raw_data)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(10)
|
||||
font.setBold(False)
|
||||
font.setWeight(50)
|
||||
font.setStyleStrategy(QtGui.QFont.PreferAntialias)
|
||||
self.groupBox_13.setFont(font)
|
||||
self.groupBox_13.setObjectName("groupBox_13")
|
||||
self.verticalLayout_13 = QtWidgets.QVBoxLayout(self.groupBox_13)
|
||||
self.verticalLayout_13.setContentsMargins(0, 0, 0, 0)
|
||||
self.verticalLayout_13.setSpacing(0)
|
||||
self.verticalLayout_13.setObjectName("verticalLayout_13")
|
||||
self.textBrowser_log = QtWidgets.QTextBrowser(self.groupBox_13)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.textBrowser_log.sizePolicy().hasHeightForWidth())
|
||||
self.textBrowser_log.setSizePolicy(sizePolicy)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(8)
|
||||
font.setBold(False)
|
||||
font.setWeight(50)
|
||||
font.setStyleStrategy(QtGui.QFont.PreferAntialias)
|
||||
self.textBrowser_log.setFont(font)
|
||||
self.textBrowser_log.setObjectName("textBrowser_log")
|
||||
self.verticalLayout_13.addWidget(self.textBrowser_log)
|
||||
self.groupBox_radioHeader = QtWidgets.QGroupBox(self.groupBox_13)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(10)
|
||||
font.setBold(False)
|
||||
font.setWeight(50)
|
||||
font.setStyleStrategy(QtGui.QFont.PreferAntialias)
|
||||
self.groupBox_radioHeader.setFont(font)
|
||||
self.groupBox_radioHeader.setObjectName("groupBox_radioHeader")
|
||||
self.horizontalLayout_5 = QtWidgets.QHBoxLayout(self.groupBox_radioHeader)
|
||||
self.horizontalLayout_5.setContentsMargins(0, 0, 0, 0)
|
||||
self.horizontalLayout_5.setSpacing(0)
|
||||
self.horizontalLayout_5.setObjectName("horizontalLayout_5")
|
||||
self.tableView_radioHeader = QtWidgets.QTableView(self.groupBox_radioHeader)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(8)
|
||||
font.setBold(False)
|
||||
font.setWeight(50)
|
||||
font.setStyleStrategy(QtGui.QFont.PreferAntialias)
|
||||
self.tableView_radioHeader.setFont(font)
|
||||
self.tableView_radioHeader.setAutoScrollMargin(10)
|
||||
self.tableView_radioHeader.setSortingEnabled(False)
|
||||
self.tableView_radioHeader.setObjectName("tableView_radioHeader")
|
||||
self.tableView_radioHeader.horizontalHeader().setMinimumSectionSize(12)
|
||||
self.tableView_radioHeader.verticalHeader().setDefaultSectionSize(20)
|
||||
self.tableView_radioHeader.verticalHeader().setMinimumSectionSize(10)
|
||||
self.tableView_radioHeader.verticalHeader().setStretchLastSection(True)
|
||||
self.horizontalLayout_5.addWidget(self.tableView_radioHeader)
|
||||
self.tableView_device_info = QtWidgets.QTableView(self.groupBox_radioHeader)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(8)
|
||||
font.setBold(False)
|
||||
font.setWeight(50)
|
||||
font.setStyleStrategy(QtGui.QFont.PreferAntialias)
|
||||
self.tableView_device_info.setFont(font)
|
||||
self.tableView_device_info.setAutoScrollMargin(10)
|
||||
self.tableView_device_info.setSortingEnabled(False)
|
||||
self.tableView_device_info.setObjectName("tableView_device_info")
|
||||
self.tableView_device_info.horizontalHeader().setMinimumSectionSize(12)
|
||||
self.tableView_device_info.verticalHeader().setDefaultSectionSize(20)
|
||||
self.tableView_device_info.verticalHeader().setMinimumSectionSize(10)
|
||||
self.tableView_device_info.verticalHeader().setStretchLastSection(True)
|
||||
self.horizontalLayout_5.addWidget(self.tableView_device_info)
|
||||
self.horizontalLayout_5.setStretch(0, 5)
|
||||
self.horizontalLayout_5.setStretch(1, 2)
|
||||
self.verticalLayout_13.addWidget(self.groupBox_radioHeader)
|
||||
self.verticalLayout_13.setStretch(0, 16)
|
||||
self.verticalLayout_13.setStretch(1, 1)
|
||||
self.verticalLayout_6.addWidget(self.splitter_raw_data)
|
||||
self.groupBox_radar_model = QtWidgets.QGroupBox(self.splitter_display)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(14)
|
||||
font.setBold(True)
|
||||
font.setWeight(75)
|
||||
font.setStyleStrategy(QtGui.QFont.PreferAntialias)
|
||||
self.groupBox_radar_model.setFont(font)
|
||||
self.groupBox_radar_model.setAlignment(QtCore.Qt.AlignCenter)
|
||||
self.groupBox_radar_model.setObjectName("groupBox_radar_model")
|
||||
self.verticalLayout_18 = QtWidgets.QVBoxLayout(self.groupBox_radar_model)
|
||||
self.verticalLayout_18.setContentsMargins(0, 0, 0, 0)
|
||||
self.verticalLayout_18.setSpacing(0)
|
||||
self.verticalLayout_18.setObjectName("verticalLayout_18")
|
||||
self.splitter_3 = QtWidgets.QSplitter(self.groupBox_radar_model)
|
||||
self.splitter_3.setOrientation(QtCore.Qt.Vertical)
|
||||
self.splitter_3.setObjectName("splitter_3")
|
||||
self.layoutWidget1 = QtWidgets.QWidget(self.splitter_3)
|
||||
self.layoutWidget1.setObjectName("layoutWidget1")
|
||||
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.layoutWidget1)
|
||||
self.verticalLayout_2.setContentsMargins(0, 0, 0, 0)
|
||||
self.verticalLayout_2.setSpacing(0)
|
||||
self.verticalLayout_2.setObjectName("verticalLayout_2")
|
||||
self.groupBox_15 = QtWidgets.QGroupBox(self.layoutWidget1)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(10)
|
||||
font.setBold(False)
|
||||
font.setWeight(50)
|
||||
font.setStyleStrategy(QtGui.QFont.PreferAntialias)
|
||||
self.groupBox_15.setFont(font)
|
||||
self.groupBox_15.setObjectName("groupBox_15")
|
||||
self.verticalLayout_25 = QtWidgets.QVBoxLayout(self.groupBox_15)
|
||||
self.verticalLayout_25.setContentsMargins(0, 0, 0, 0)
|
||||
self.verticalLayout_25.setSpacing(0)
|
||||
self.verticalLayout_25.setObjectName("verticalLayout_25")
|
||||
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout_2.setSpacing(9)
|
||||
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
|
||||
self.widget_25 = QtWidgets.QWidget(self.groupBox_15)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Ignored, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.widget_25.sizePolicy().hasHeightForWidth())
|
||||
self.widget_25.setSizePolicy(sizePolicy)
|
||||
self.widget_25.setObjectName("widget_25")
|
||||
self.horizontalLayout_27 = QtWidgets.QHBoxLayout(self.widget_25)
|
||||
self.horizontalLayout_27.setContentsMargins(0, 0, 0, 0)
|
||||
self.horizontalLayout_27.setSpacing(0)
|
||||
self.horizontalLayout_27.setObjectName("horizontalLayout_27")
|
||||
self.widget_39 = QtWidgets.QWidget(self.widget_25)
|
||||
self.widget_39.setObjectName("widget_39")
|
||||
self.horizontalLayout_38 = QtWidgets.QHBoxLayout(self.widget_39)
|
||||
self.horizontalLayout_38.setContentsMargins(0, 0, 0, 0)
|
||||
self.horizontalLayout_38.setSpacing(0)
|
||||
self.horizontalLayout_38.setObjectName("horizontalLayout_38")
|
||||
self.horizontalLayout_27.addWidget(self.widget_39)
|
||||
self.label_delay_5 = QtWidgets.QLabel(self.widget_25)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.label_delay_5.sizePolicy().hasHeightForWidth())
|
||||
self.label_delay_5.setSizePolicy(sizePolicy)
|
||||
self.label_delay_5.setObjectName("label_delay_5")
|
||||
self.horizontalLayout_27.addWidget(self.label_delay_5)
|
||||
self.timeEdit_train_delay = QtWidgets.QTimeEdit(self.widget_25)
|
||||
self.timeEdit_train_delay.setMaximumDateTime(QtCore.QDateTime(QtCore.QDate(2000, 1, 1), QtCore.QTime(23, 59, 59)))
|
||||
self.timeEdit_train_delay.setCurrentSection(QtWidgets.QDateTimeEdit.MinuteSection)
|
||||
self.timeEdit_train_delay.setCurrentSectionIndex(1)
|
||||
self.timeEdit_train_delay.setTime(QtCore.QTime(0, 0, 0))
|
||||
self.timeEdit_train_delay.setObjectName("timeEdit_train_delay")
|
||||
self.horizontalLayout_27.addWidget(self.timeEdit_train_delay)
|
||||
self.horizontalLayout_27.setStretch(1, 2)
|
||||
self.horizontalLayout_27.setStretch(2, 3)
|
||||
self.horizontalLayout_2.addWidget(self.widget_25)
|
||||
self.widget_26 = QtWidgets.QWidget(self.groupBox_15)
|
||||
self.widget_26.setObjectName("widget_26")
|
||||
self.horizontalLayout_28 = QtWidgets.QHBoxLayout(self.widget_26)
|
||||
self.horizontalLayout_28.setContentsMargins(9, 0, 0, 0)
|
||||
self.horizontalLayout_28.setSpacing(0)
|
||||
self.horizontalLayout_28.setObjectName("horizontalLayout_28")
|
||||
self.label_delay_6 = QtWidgets.QLabel(self.widget_26)
|
||||
self.label_delay_6.setObjectName("label_delay_6")
|
||||
self.horizontalLayout_28.addWidget(self.label_delay_6)
|
||||
self.timeEdit_train_duration = QtWidgets.QTimeEdit(self.widget_26)
|
||||
self.timeEdit_train_duration.setMaximumDateTime(QtCore.QDateTime(QtCore.QDate(2000, 1, 1), QtCore.QTime(23, 59, 59)))
|
||||
self.timeEdit_train_duration.setCurrentSection(QtWidgets.QDateTimeEdit.SecondSection)
|
||||
self.timeEdit_train_duration.setCurrentSectionIndex(2)
|
||||
self.timeEdit_train_duration.setTime(QtCore.QTime(0, 0, 10))
|
||||
self.timeEdit_train_duration.setObjectName("timeEdit_train_duration")
|
||||
self.horizontalLayout_28.addWidget(self.timeEdit_train_duration)
|
||||
self.horizontalLayout_28.setStretch(0, 2)
|
||||
self.horizontalLayout_28.setStretch(1, 3)
|
||||
self.horizontalLayout_2.addWidget(self.widget_26)
|
||||
self.checkBox_train_add = QtWidgets.QCheckBox(self.groupBox_15)
|
||||
self.checkBox_train_add.setEnabled(True)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.checkBox_train_add.sizePolicy().hasHeightForWidth())
|
||||
self.checkBox_train_add.setSizePolicy(sizePolicy)
|
||||
self.checkBox_train_add.setObjectName("checkBox_train_add")
|
||||
self.horizontalLayout_2.addWidget(self.checkBox_train_add)
|
||||
self.pushButton_train_start = QtWidgets.QPushButton(self.groupBox_15)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(14)
|
||||
font.setBold(False)
|
||||
font.setWeight(50)
|
||||
font.setStyleStrategy(QtGui.QFont.PreferAntialias)
|
||||
self.pushButton_train_start.setFont(font)
|
||||
self.pushButton_train_start.setIconSize(QtCore.QSize(8, 8))
|
||||
self.pushButton_train_start.setAutoDefault(False)
|
||||
self.pushButton_train_start.setDefault(False)
|
||||
self.pushButton_train_start.setObjectName("pushButton_train_start")
|
||||
self.horizontalLayout_2.addWidget(self.pushButton_train_start)
|
||||
self.horizontalLayout_2.setStretch(0, 1)
|
||||
self.horizontalLayout_2.setStretch(1, 1)
|
||||
self.horizontalLayout_2.setStretch(2, 1)
|
||||
self.horizontalLayout_2.setStretch(3, 1)
|
||||
self.verticalLayout_25.addLayout(self.horizontalLayout_2)
|
||||
self.verticalLayout_2.addWidget(self.groupBox_15)
|
||||
self.groupBox_14 = QtWidgets.QGroupBox(self.layoutWidget1)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(10)
|
||||
font.setBold(False)
|
||||
font.setWeight(50)
|
||||
font.setStyleStrategy(QtGui.QFont.PreferAntialias)
|
||||
self.groupBox_14.setFont(font)
|
||||
self.groupBox_14.setObjectName("groupBox_14")
|
||||
self.verticalLayout_5 = QtWidgets.QVBoxLayout(self.groupBox_14)
|
||||
self.verticalLayout_5.setContentsMargins(0, 0, 0, 0)
|
||||
self.verticalLayout_5.setSpacing(0)
|
||||
self.verticalLayout_5.setObjectName("verticalLayout_5")
|
||||
self.horizontalLayout_10 = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout_10.setObjectName("horizontalLayout_10")
|
||||
self.widget_31 = QtWidgets.QWidget(self.groupBox_14)
|
||||
self.widget_31.setObjectName("widget_31")
|
||||
self.horizontalLayout_45 = QtWidgets.QHBoxLayout(self.widget_31)
|
||||
self.horizontalLayout_45.setContentsMargins(0, 0, 0, 0)
|
||||
self.horizontalLayout_45.setSpacing(9)
|
||||
self.horizontalLayout_45.setObjectName("horizontalLayout_45")
|
||||
self.label_number_3 = QtWidgets.QLabel(self.widget_31)
|
||||
self.label_number_3.setObjectName("label_number_3")
|
||||
self.horizontalLayout_45.addWidget(self.label_number_3)
|
||||
self.doubleSpinBox_predict_someone_sensitivity = QtWidgets.QDoubleSpinBox(self.widget_31)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.doubleSpinBox_predict_someone_sensitivity.sizePolicy().hasHeightForWidth())
|
||||
self.doubleSpinBox_predict_someone_sensitivity.setSizePolicy(sizePolicy)
|
||||
self.doubleSpinBox_predict_someone_sensitivity.setDecimals(2)
|
||||
self.doubleSpinBox_predict_someone_sensitivity.setMinimum(0.01)
|
||||
self.doubleSpinBox_predict_someone_sensitivity.setMaximum(1.0)
|
||||
self.doubleSpinBox_predict_someone_sensitivity.setSingleStep(0.01)
|
||||
self.doubleSpinBox_predict_someone_sensitivity.setProperty("value", 0.2)
|
||||
self.doubleSpinBox_predict_someone_sensitivity.setObjectName("doubleSpinBox_predict_someone_sensitivity")
|
||||
self.horizontalLayout_45.addWidget(self.doubleSpinBox_predict_someone_sensitivity)
|
||||
self.label_number_5 = QtWidgets.QLabel(self.widget_31)
|
||||
self.label_number_5.setObjectName("label_number_5")
|
||||
self.horizontalLayout_45.addWidget(self.label_number_5)
|
||||
self.doubleSpinBox_predict_move_sensitivity = QtWidgets.QDoubleSpinBox(self.widget_31)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.doubleSpinBox_predict_move_sensitivity.sizePolicy().hasHeightForWidth())
|
||||
self.doubleSpinBox_predict_move_sensitivity.setSizePolicy(sizePolicy)
|
||||
self.doubleSpinBox_predict_move_sensitivity.setDecimals(2)
|
||||
self.doubleSpinBox_predict_move_sensitivity.setMinimum(0.01)
|
||||
self.doubleSpinBox_predict_move_sensitivity.setMaximum(1.0)
|
||||
self.doubleSpinBox_predict_move_sensitivity.setSingleStep(0.01)
|
||||
self.doubleSpinBox_predict_move_sensitivity.setProperty("value", 0.2)
|
||||
self.doubleSpinBox_predict_move_sensitivity.setObjectName("doubleSpinBox_predict_move_sensitivity")
|
||||
self.horizontalLayout_45.addWidget(self.doubleSpinBox_predict_move_sensitivity)
|
||||
self.label_duration_7 = QtWidgets.QLabel(self.widget_31)
|
||||
self.label_duration_7.setObjectName("label_duration_7")
|
||||
self.horizontalLayout_45.addWidget(self.label_duration_7)
|
||||
self.spinBox_predict_buffer_size = QtWidgets.QSpinBox(self.widget_31)
|
||||
self.spinBox_predict_buffer_size.setMinimum(1)
|
||||
self.spinBox_predict_buffer_size.setProperty("value", 5)
|
||||
self.spinBox_predict_buffer_size.setDisplayIntegerBase(10)
|
||||
self.spinBox_predict_buffer_size.setObjectName("spinBox_predict_buffer_size")
|
||||
self.horizontalLayout_45.addWidget(self.spinBox_predict_buffer_size)
|
||||
self.spinBox_predict_outliers_number = QtWidgets.QSpinBox(self.widget_31)
|
||||
self.spinBox_predict_outliers_number.setMinimum(1)
|
||||
self.spinBox_predict_outliers_number.setMaximum(99)
|
||||
self.spinBox_predict_outliers_number.setSingleStep(1)
|
||||
self.spinBox_predict_outliers_number.setProperty("value", 2)
|
||||
self.spinBox_predict_outliers_number.setDisplayIntegerBase(10)
|
||||
self.spinBox_predict_outliers_number.setObjectName("spinBox_predict_outliers_number")
|
||||
self.horizontalLayout_45.addWidget(self.spinBox_predict_outliers_number)
|
||||
self.checkBox_display_eigenvalues_table = QtWidgets.QCheckBox(self.widget_31)
|
||||
self.checkBox_display_eigenvalues_table.setObjectName("checkBox_display_eigenvalues_table")
|
||||
self.horizontalLayout_45.addWidget(self.checkBox_display_eigenvalues_table)
|
||||
self.pushButton_predict_config = QtWidgets.QPushButton(self.widget_31)
|
||||
self.pushButton_predict_config.setObjectName("pushButton_predict_config")
|
||||
self.horizontalLayout_45.addWidget(self.pushButton_predict_config)
|
||||
self.horizontalLayout_45.setStretch(0, 3)
|
||||
self.horizontalLayout_45.setStretch(1, 2)
|
||||
self.horizontalLayout_45.setStretch(2, 3)
|
||||
self.horizontalLayout_45.setStretch(3, 2)
|
||||
self.horizontalLayout_45.setStretch(4, 2)
|
||||
self.horizontalLayout_45.setStretch(5, 1)
|
||||
self.horizontalLayout_45.setStretch(6, 1)
|
||||
self.horizontalLayout_45.setStretch(7, 2)
|
||||
self.horizontalLayout_45.setStretch(8, 3)
|
||||
self.horizontalLayout_10.addWidget(self.widget_31)
|
||||
self.verticalLayout_5.addLayout(self.horizontalLayout_10)
|
||||
self.splitter_eigenvalues = QtWidgets.QSplitter(self.groupBox_14)
|
||||
self.splitter_eigenvalues.setOrientation(QtCore.Qt.Horizontal)
|
||||
self.splitter_eigenvalues.setObjectName("splitter_eigenvalues")
|
||||
self.graphicsView_eigenvalues = PlotWidget(self.splitter_eigenvalues)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.graphicsView_eigenvalues.sizePolicy().hasHeightForWidth())
|
||||
self.graphicsView_eigenvalues.setSizePolicy(sizePolicy)
|
||||
self.graphicsView_eigenvalues.setObjectName("graphicsView_eigenvalues")
|
||||
self.tableView_eigenvalues = QtWidgets.QWidget(self.splitter_eigenvalues)
|
||||
self.tableView_eigenvalues.setObjectName("tableView_eigenvalues")
|
||||
self.tableView_eigenvalues_QVBoxLayout = QtWidgets.QVBoxLayout(self.tableView_eigenvalues)
|
||||
self.tableView_eigenvalues_QVBoxLayout.setContentsMargins(0, 0, 0, 0)
|
||||
self.tableView_eigenvalues_QVBoxLayout.setSpacing(0)
|
||||
self.tableView_eigenvalues_QVBoxLayout.setObjectName("tableView_eigenvalues_QVBoxLayout")
|
||||
self.tableView_radar_data_room = QtWidgets.QTableView(self.tableView_eigenvalues)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(8)
|
||||
font.setBold(False)
|
||||
font.setWeight(50)
|
||||
font.setStyleStrategy(QtGui.QFont.PreferAntialias)
|
||||
self.tableView_radar_data_room.setFont(font)
|
||||
self.tableView_radar_data_room.setAutoScrollMargin(10)
|
||||
self.tableView_radar_data_room.setSortingEnabled(False)
|
||||
self.tableView_radar_data_room.setObjectName("tableView_radar_data_room")
|
||||
self.tableView_radar_data_room.horizontalHeader().setMinimumSectionSize(12)
|
||||
self.tableView_radar_data_room.verticalHeader().setDefaultSectionSize(20)
|
||||
self.tableView_radar_data_room.verticalHeader().setMinimumSectionSize(10)
|
||||
self.tableView_radar_data_room.verticalHeader().setStretchLastSection(True)
|
||||
self.tableView_eigenvalues_QVBoxLayout.addWidget(self.tableView_radar_data_room)
|
||||
self.tableView_radar_data_human = QtWidgets.QTableView(self.tableView_eigenvalues)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(8)
|
||||
font.setBold(False)
|
||||
font.setWeight(50)
|
||||
font.setStyleStrategy(QtGui.QFont.PreferAntialias)
|
||||
self.tableView_radar_data_human.setFont(font)
|
||||
self.tableView_radar_data_human.setAutoScrollMargin(10)
|
||||
self.tableView_radar_data_human.setSortingEnabled(False)
|
||||
self.tableView_radar_data_human.setObjectName("tableView_radar_data_human")
|
||||
self.tableView_radar_data_human.horizontalHeader().setMinimumSectionSize(12)
|
||||
self.tableView_radar_data_human.verticalHeader().setDefaultSectionSize(20)
|
||||
self.tableView_radar_data_human.verticalHeader().setMinimumSectionSize(10)
|
||||
self.tableView_radar_data_human.verticalHeader().setStretchLastSection(True)
|
||||
self.tableView_eigenvalues_QVBoxLayout.addWidget(self.tableView_radar_data_human)
|
||||
self.verticalLayout_5.addWidget(self.splitter_eigenvalues)
|
||||
self.verticalLayout_5.setStretch(0, 1)
|
||||
self.verticalLayout_5.setStretch(1, 64)
|
||||
self.verticalLayout_2.addWidget(self.groupBox_14)
|
||||
self.verticalLayout_2.setStretch(0, 1)
|
||||
self.verticalLayout_2.setStretch(1, 32)
|
||||
self.groupBox_19 = QtWidgets.QGroupBox(self.splitter_3)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(10)
|
||||
font.setBold(False)
|
||||
font.setWeight(50)
|
||||
font.setStyleStrategy(QtGui.QFont.PreferAntialias)
|
||||
self.groupBox_19.setFont(font)
|
||||
self.groupBox_19.setObjectName("groupBox_19")
|
||||
self.verticalLayout = QtWidgets.QVBoxLayout(self.groupBox_19)
|
||||
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
|
||||
self.verticalLayout.setSpacing(0)
|
||||
self.verticalLayout.setObjectName("verticalLayout")
|
||||
self.horizontalLayout_12 = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout_12.setSpacing(9)
|
||||
self.horizontalLayout_12.setObjectName("horizontalLayout_12")
|
||||
self.widget_38 = QtWidgets.QWidget(self.groupBox_19)
|
||||
self.widget_38.setObjectName("widget_38")
|
||||
self.horizontalLayout_41 = QtWidgets.QHBoxLayout(self.widget_38)
|
||||
self.horizontalLayout_41.setContentsMargins(0, 0, 0, 0)
|
||||
self.horizontalLayout_41.setSpacing(6)
|
||||
self.horizontalLayout_41.setObjectName("horizontalLayout_41")
|
||||
self.label_target_5 = QtWidgets.QLabel(self.widget_38)
|
||||
self.label_target_5.setObjectName("label_target_5")
|
||||
self.horizontalLayout_41.addWidget(self.label_target_5)
|
||||
self.comboBox_statistics_mode = QtWidgets.QComboBox(self.widget_38)
|
||||
self.comboBox_statistics_mode.setObjectName("comboBox_statistics_mode")
|
||||
self.comboBox_statistics_mode.addItem("")
|
||||
self.comboBox_statistics_mode.addItem("")
|
||||
self.comboBox_statistics_mode.addItem("")
|
||||
self.horizontalLayout_41.addWidget(self.comboBox_statistics_mode)
|
||||
self.label_delay_9 = QtWidgets.QLabel(self.widget_38)
|
||||
self.label_delay_9.setObjectName("label_delay_9")
|
||||
self.horizontalLayout_41.addWidget(self.label_delay_9)
|
||||
self.dateTimeEdit_statistics_time = QtWidgets.QDateTimeEdit(self.widget_38)
|
||||
self.dateTimeEdit_statistics_time.setDateTime(QtCore.QDateTime(QtCore.QDate(2022, 7, 9), QtCore.QTime(0, 0, 0)))
|
||||
self.dateTimeEdit_statistics_time.setMaximumDateTime(QtCore.QDateTime(QtCore.QDate(2030, 9, 14), QtCore.QTime(0, 0, 0)))
|
||||
self.dateTimeEdit_statistics_time.setMinimumDateTime(QtCore.QDateTime(QtCore.QDate(2022, 7, 1), QtCore.QTime(0, 0, 0)))
|
||||
self.dateTimeEdit_statistics_time.setCurrentSection(QtWidgets.QDateTimeEdit.MinuteSection)
|
||||
self.dateTimeEdit_statistics_time.setCalendarPopup(False)
|
||||
self.dateTimeEdit_statistics_time.setCurrentSectionIndex(4)
|
||||
self.dateTimeEdit_statistics_time.setTimeSpec(QtCore.Qt.LocalTime)
|
||||
self.dateTimeEdit_statistics_time.setObjectName("dateTimeEdit_statistics_time")
|
||||
self.horizontalLayout_41.addWidget(self.dateTimeEdit_statistics_time)
|
||||
spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
||||
self.horizontalLayout_41.addItem(spacerItem1)
|
||||
self.checkBox_statistics_auto_update = QtWidgets.QCheckBox(self.widget_38)
|
||||
self.checkBox_statistics_auto_update.setChecked(True)
|
||||
self.checkBox_statistics_auto_update.setObjectName("checkBox_statistics_auto_update")
|
||||
self.horizontalLayout_41.addWidget(self.checkBox_statistics_auto_update)
|
||||
self.pushButton_statistics_config = QtWidgets.QPushButton(self.widget_38)
|
||||
self.pushButton_statistics_config.setObjectName("pushButton_statistics_config")
|
||||
self.horizontalLayout_41.addWidget(self.pushButton_statistics_config)
|
||||
self.horizontalLayout_41.setStretch(0, 1)
|
||||
self.horizontalLayout_41.setStretch(1, 4)
|
||||
self.horizontalLayout_41.setStretch(2, 1)
|
||||
self.horizontalLayout_41.setStretch(3, 4)
|
||||
self.horizontalLayout_41.setStretch(4, 6)
|
||||
self.horizontalLayout_41.setStretch(5, 1)
|
||||
self.horizontalLayout_41.setStretch(6, 2)
|
||||
self.horizontalLayout_12.addWidget(self.widget_38)
|
||||
self.verticalLayout.addLayout(self.horizontalLayout_12)
|
||||
self.splitter_status_record = QtWidgets.QSplitter(self.groupBox_19)
|
||||
self.splitter_status_record.setOrientation(QtCore.Qt.Horizontal)
|
||||
self.splitter_status_record.setObjectName("splitter_status_record")
|
||||
self.graphicsView_status_record = PlotWidget(self.splitter_status_record)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.graphicsView_status_record.sizePolicy().hasHeightForWidth())
|
||||
self.graphicsView_status_record.setSizePolicy(sizePolicy)
|
||||
self.graphicsView_status_record.setObjectName("graphicsView_status_record")
|
||||
self.tableView_status_record = QtWidgets.QTableView(self.splitter_status_record)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(8)
|
||||
font.setBold(False)
|
||||
font.setWeight(50)
|
||||
font.setStyleStrategy(QtGui.QFont.PreferAntialias)
|
||||
self.tableView_status_record.setFont(font)
|
||||
self.tableView_status_record.setAutoScrollMargin(10)
|
||||
self.tableView_status_record.setSortingEnabled(False)
|
||||
self.tableView_status_record.setObjectName("tableView_status_record")
|
||||
self.tableView_status_record.horizontalHeader().setMinimumSectionSize(12)
|
||||
self.tableView_status_record.verticalHeader().setCascadingSectionResizes(True)
|
||||
self.tableView_status_record.verticalHeader().setDefaultSectionSize(20)
|
||||
self.tableView_status_record.verticalHeader().setMinimumSectionSize(5)
|
||||
self.tableView_status_record.verticalHeader().setStretchLastSection(True)
|
||||
self.verticalLayout.addWidget(self.splitter_status_record)
|
||||
self.verticalLayout.setStretch(0, 1)
|
||||
self.verticalLayout.setStretch(1, 64)
|
||||
self.layoutWidget2 = QtWidgets.QWidget(self.splitter_3)
|
||||
self.layoutWidget2.setObjectName("layoutWidget2")
|
||||
self.verticalLayout_14 = QtWidgets.QVBoxLayout(self.layoutWidget2)
|
||||
self.verticalLayout_14.setContentsMargins(0, 0, 0, 0)
|
||||
self.verticalLayout_14.setSpacing(0)
|
||||
self.verticalLayout_14.setObjectName("verticalLayout_14")
|
||||
self.groupBox_18 = QtWidgets.QGroupBox(self.layoutWidget2)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(10)
|
||||
font.setBold(False)
|
||||
font.setWeight(50)
|
||||
font.setStyleStrategy(QtGui.QFont.PreferAntialias)
|
||||
self.groupBox_18.setFont(font)
|
||||
self.groupBox_18.setObjectName("groupBox_18")
|
||||
self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.groupBox_18)
|
||||
self.verticalLayout_3.setContentsMargins(0, 0, 0, 0)
|
||||
self.verticalLayout_3.setSpacing(0)
|
||||
self.verticalLayout_3.setObjectName("verticalLayout_3")
|
||||
self.horizontalLayout_9 = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout_9.setSpacing(9)
|
||||
self.horizontalLayout_9.setObjectName("horizontalLayout_9")
|
||||
self.label_target_4 = QtWidgets.QLabel(self.groupBox_18)
|
||||
self.label_target_4.setObjectName("label_target_4")
|
||||
self.horizontalLayout_9.addWidget(self.label_target_4)
|
||||
self.comboBox_collect_target = QtWidgets.QComboBox(self.groupBox_18)
|
||||
self.comboBox_collect_target.setObjectName("comboBox_collect_target")
|
||||
self.comboBox_collect_target.addItem("")
|
||||
self.comboBox_collect_target.addItem("")
|
||||
self.comboBox_collect_target.addItem("")
|
||||
self.comboBox_collect_target.addItem("")
|
||||
self.comboBox_collect_target.addItem("")
|
||||
self.comboBox_collect_target.addItem("")
|
||||
self.comboBox_collect_target.addItem("")
|
||||
self.comboBox_collect_target.addItem("")
|
||||
self.comboBox_collect_target.addItem("")
|
||||
self.comboBox_collect_target.addItem("")
|
||||
self.comboBox_collect_target.addItem("")
|
||||
self.comboBox_collect_target.addItem("")
|
||||
self.comboBox_collect_target.addItem("")
|
||||
self.comboBox_collect_target.addItem("")
|
||||
self.comboBox_collect_target.addItem("")
|
||||
self.comboBox_collect_target.addItem("")
|
||||
self.comboBox_collect_target.addItem("")
|
||||
self.horizontalLayout_9.addWidget(self.comboBox_collect_target)
|
||||
self.label_delay = QtWidgets.QLabel(self.groupBox_18)
|
||||
self.label_delay.setObjectName("label_delay")
|
||||
self.horizontalLayout_9.addWidget(self.label_delay)
|
||||
self.timeEdit_collect_delay = QtWidgets.QTimeEdit(self.groupBox_18)
|
||||
self.timeEdit_collect_delay.setMaximumDateTime(QtCore.QDateTime(QtCore.QDate(2000, 1, 1), QtCore.QTime(23, 59, 59)))
|
||||
self.timeEdit_collect_delay.setCurrentSection(QtWidgets.QDateTimeEdit.MinuteSection)
|
||||
self.timeEdit_collect_delay.setCurrentSectionIndex(1)
|
||||
self.timeEdit_collect_delay.setTime(QtCore.QTime(0, 0, 0))
|
||||
self.timeEdit_collect_delay.setObjectName("timeEdit_collect_delay")
|
||||
self.horizontalLayout_9.addWidget(self.timeEdit_collect_delay)
|
||||
self.label_duration = QtWidgets.QLabel(self.groupBox_18)
|
||||
self.label_duration.setObjectName("label_duration")
|
||||
self.horizontalLayout_9.addWidget(self.label_duration)
|
||||
self.spinBox_collect_duration = QtWidgets.QSpinBox(self.groupBox_18)
|
||||
self.spinBox_collect_duration.setMinimum(50)
|
||||
self.spinBox_collect_duration.setMaximum(100000000)
|
||||
self.spinBox_collect_duration.setSingleStep(10)
|
||||
self.spinBox_collect_duration.setProperty("value", 500)
|
||||
self.spinBox_collect_duration.setDisplayIntegerBase(10)
|
||||
self.spinBox_collect_duration.setObjectName("spinBox_collect_duration")
|
||||
self.horizontalLayout_9.addWidget(self.spinBox_collect_duration)
|
||||
self.label_number = QtWidgets.QLabel(self.groupBox_18)
|
||||
self.label_number.setObjectName("label_number")
|
||||
self.horizontalLayout_9.addWidget(self.label_number)
|
||||
self.spinBox_collect_number = QtWidgets.QSpinBox(self.groupBox_18)
|
||||
self.spinBox_collect_number.setMinimum(0)
|
||||
self.spinBox_collect_number.setMaximum(10000)
|
||||
self.spinBox_collect_number.setProperty("value", 1)
|
||||
self.spinBox_collect_number.setObjectName("spinBox_collect_number")
|
||||
self.horizontalLayout_9.addWidget(self.spinBox_collect_number)
|
||||
self.pushButton_collect_clean = QtWidgets.QPushButton(self.groupBox_18)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(10)
|
||||
font.setBold(False)
|
||||
font.setWeight(50)
|
||||
font.setStyleStrategy(QtGui.QFont.PreferAntialias)
|
||||
self.pushButton_collect_clean.setFont(font)
|
||||
self.pushButton_collect_clean.setObjectName("pushButton_collect_clean")
|
||||
self.horizontalLayout_9.addWidget(self.pushButton_collect_clean)
|
||||
self.pushButton_collect_start = QtWidgets.QPushButton(self.groupBox_18)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(10)
|
||||
font.setBold(False)
|
||||
font.setWeight(50)
|
||||
font.setStyleStrategy(QtGui.QFont.PreferAntialias)
|
||||
self.pushButton_collect_start.setFont(font)
|
||||
self.pushButton_collect_start.setAutoDefault(False)
|
||||
self.pushButton_collect_start.setDefault(False)
|
||||
self.pushButton_collect_start.setObjectName("pushButton_collect_start")
|
||||
self.horizontalLayout_9.addWidget(self.pushButton_collect_start)
|
||||
self.horizontalLayout_9.setStretch(0, 1)
|
||||
self.horizontalLayout_9.setStretch(1, 3)
|
||||
self.horizontalLayout_9.setStretch(2, 1)
|
||||
self.horizontalLayout_9.setStretch(3, 3)
|
||||
self.horizontalLayout_9.setStretch(4, 1)
|
||||
self.horizontalLayout_9.setStretch(5, 3)
|
||||
self.horizontalLayout_9.setStretch(6, 1)
|
||||
self.horizontalLayout_9.setStretch(7, 3)
|
||||
self.horizontalLayout_9.setStretch(8, 1)
|
||||
self.horizontalLayout_9.setStretch(9, 3)
|
||||
self.verticalLayout_3.addLayout(self.horizontalLayout_9)
|
||||
self.verticalLayout_14.addWidget(self.groupBox_18)
|
||||
self.verticalLayout_14.setStretch(0, 1)
|
||||
self.verticalLayout_14.setStretch(1, 32)
|
||||
self.verticalLayout_18.addWidget(self.splitter_3)
|
||||
self.verticalLayout_17.addWidget(self.splitter_display)
|
||||
self.verticalLayout_17.setStretch(0, 1)
|
||||
self.verticalLayout_17.setStretch(1, 128)
|
||||
MainWindow.setCentralWidget(self.centralwidget)
|
||||
|
||||
self.retranslateUi(MainWindow)
|
||||
QtCore.QMetaObject.connectSlotsByName(MainWindow)
|
||||
MainWindow.setTabOrder(self.graphicsView_subcarrier, self.graphicsView_rssi)
|
||||
|
||||
def retranslateUi(self, MainWindow):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
MainWindow.setWindowTitle(_translate("MainWindow", "ESP_CSI_TOOL"))
|
||||
self.label_2.setText(_translate("MainWindow", "display:"))
|
||||
self.checkBox_raw_data.setText(_translate("MainWindow", "Raw data"))
|
||||
self.checkBox_radar_model.setText(_translate("MainWindow", "Radar model"))
|
||||
self.groupBox_raw_data.setTitle(_translate("MainWindow", "Raw data"))
|
||||
self.groupBox_16.setTitle(_translate("MainWindow", "Command"))
|
||||
self.groupBox_11.setTitle(_translate("MainWindow", "router"))
|
||||
self.label_delay_2.setText(_translate("MainWindow", "ssid "))
|
||||
self.label_duration_2.setText(_translate("MainWindow", "password"))
|
||||
self.checkBox_router_auto_connect.setText(_translate("MainWindow", "atuto connect"))
|
||||
self.pushButton_router_connect.setText(_translate("MainWindow", "connect"))
|
||||
self.label.setText(_translate("MainWindow", "custom"))
|
||||
self.comboBox_command.setItemText(0, _translate("MainWindow", "NULL"))
|
||||
self.comboBox_command.setItemText(1, _translate("MainWindow", "restart"))
|
||||
self.comboBox_command.setItemText(2, _translate("MainWindow", "radar --output LLFT"))
|
||||
self.comboBox_command.setItemText(3, _translate("MainWindow", "version"))
|
||||
self.comboBox_command.setItemText(4, _translate("MainWindow", "wifi_config --info"))
|
||||
self.comboBox_command.setItemText(5, _translate("MainWindow", "wifi_scan"))
|
||||
self.comboBox_command.setItemText(6, _translate("MainWindow", "ping --abort"))
|
||||
self.pushButton_command.setText(_translate("MainWindow", "send"))
|
||||
self.groupBox_subcarrier.setTitle(_translate("MainWindow", "subcarrier amplitude"))
|
||||
self.checkBox_wave_filtering.setText(_translate("MainWindow", "wave filtering"))
|
||||
self.groupBox_rssi.setTitle(_translate("MainWindow", "RSSI"))
|
||||
self.groupBox_13.setTitle(_translate("MainWindow", "log"))
|
||||
self.groupBox_radioHeader.setTitle(_translate("MainWindow", "info"))
|
||||
self.groupBox_radar_model.setTitle(_translate("MainWindow", "Radar model"))
|
||||
self.groupBox_15.setTitle(_translate("MainWindow", "Train"))
|
||||
self.label_delay_5.setText(_translate("MainWindow", "delay"))
|
||||
self.timeEdit_train_delay.setDisplayFormat(_translate("MainWindow", "HH:mm:ss"))
|
||||
self.label_delay_6.setText(_translate("MainWindow", "duration"))
|
||||
self.timeEdit_train_duration.setDisplayFormat(_translate("MainWindow", "HH:mm:ss"))
|
||||
self.checkBox_train_add.setText(_translate("MainWindow", "Add"))
|
||||
self.pushButton_train_start.setText(_translate("MainWindow", "start"))
|
||||
self.groupBox_14.setTitle(_translate("MainWindow", "Predict"))
|
||||
self.label_number_3.setText(_translate("MainWindow", "someone sensitivity"))
|
||||
self.label_number_5.setText(_translate("MainWindow", "move sensitivity"))
|
||||
self.label_duration_7.setText(_translate("MainWindow", "filter outliers"))
|
||||
self.checkBox_display_eigenvalues_table.setText(_translate("MainWindow", "display table"))
|
||||
self.pushButton_predict_config.setText(_translate("MainWindow", "config"))
|
||||
self.groupBox_19.setTitle(_translate("MainWindow", "Statistics"))
|
||||
self.label_target_5.setText(_translate("MainWindow", "mode"))
|
||||
self.comboBox_statistics_mode.setItemText(0, _translate("MainWindow", "minute"))
|
||||
self.comboBox_statistics_mode.setItemText(1, _translate("MainWindow", "hour"))
|
||||
self.comboBox_statistics_mode.setItemText(2, _translate("MainWindow", "day"))
|
||||
self.label_delay_9.setText(_translate("MainWindow", "time"))
|
||||
self.dateTimeEdit_statistics_time.setDisplayFormat(_translate("MainWindow", "yyyy-MM-dd HH:mm:ss"))
|
||||
self.checkBox_statistics_auto_update.setText(_translate("MainWindow", "auto update"))
|
||||
self.pushButton_statistics_config.setText(_translate("MainWindow", "update"))
|
||||
self.groupBox_18.setTitle(_translate("MainWindow", "Collect"))
|
||||
self.label_target_4.setText(_translate("MainWindow", "target"))
|
||||
self.comboBox_collect_target.setItemText(0, _translate("MainWindow", "unknown"))
|
||||
self.comboBox_collect_target.setItemText(1, _translate("MainWindow", "train"))
|
||||
self.comboBox_collect_target.setItemText(2, _translate("MainWindow", "none"))
|
||||
self.comboBox_collect_target.setItemText(3, _translate("MainWindow", "someone"))
|
||||
self.comboBox_collect_target.setItemText(4, _translate("MainWindow", "static"))
|
||||
self.comboBox_collect_target.setItemText(5, _translate("MainWindow", "move"))
|
||||
self.comboBox_collect_target.setItemText(6, _translate("MainWindow", "front"))
|
||||
self.comboBox_collect_target.setItemText(7, _translate("MainWindow", "after"))
|
||||
self.comboBox_collect_target.setItemText(8, _translate("MainWindow", "left"))
|
||||
self.comboBox_collect_target.setItemText(9, _translate("MainWindow", "right"))
|
||||
self.comboBox_collect_target.setItemText(10, _translate("MainWindow", "go"))
|
||||
self.comboBox_collect_target.setItemText(11, _translate("MainWindow", "jump"))
|
||||
self.comboBox_collect_target.setItemText(12, _translate("MainWindow", "sit down"))
|
||||
self.comboBox_collect_target.setItemText(13, _translate("MainWindow", "stand up"))
|
||||
self.comboBox_collect_target.setItemText(14, _translate("MainWindow", "climb up"))
|
||||
self.comboBox_collect_target.setItemText(15, _translate("MainWindow", "wave"))
|
||||
self.comboBox_collect_target.setItemText(16, _translate("MainWindow", "applause"))
|
||||
self.label_delay.setText(_translate("MainWindow", "delay"))
|
||||
self.timeEdit_collect_delay.setDisplayFormat(_translate("MainWindow", "HH:mm:ss"))
|
||||
self.label_duration.setText(_translate("MainWindow", "duration(ms)"))
|
||||
self.label_number.setText(_translate("MainWindow", "number"))
|
||||
self.pushButton_collect_clean.setText(_translate("MainWindow", "clean"))
|
||||
self.pushButton_collect_start.setText(_translate("MainWindow", "start"))
|
||||
from pyqtgraph import PlotWidget
|
||||
1665
esp-radar/console_test/tools/esp_csi_tool_gui.ui
Normal file
1665
esp-radar/console_test/tools/esp_csi_tool_gui.ui
Normal file
File diff suppressed because it is too large
Load Diff
8
esp-radar/console_test/tools/requirements.txt
Normal file
8
esp-radar/console_test/tools/requirements.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
argparse
|
||||
pandas
|
||||
numpy
|
||||
path
|
||||
PyQt5
|
||||
pyqtgraph
|
||||
pyserial
|
||||
scipy
|
||||
Reference in New Issue
Block a user