添加 USB 主机、BLE 和 Socket 数据端口驱动程序:

- 支持大容量存储类(MSC)的 USB 主机驱动程序
- BLE SPP(串行端口配置文件)客户端和服务器实现
- Socket(UDP/TCP)数据端口驱动程序
- 相关的 shell 接口用于配置和测试
This commit is contained in:
LokLiang
2025-02-21 12:43:26 +08:00
parent e9b5e42ef2
commit 9cf47ff0a8
43 changed files with 12463 additions and 3 deletions

View File

@@ -0,0 +1,15 @@
#include "socket_inet.h"
/**
* @brief 初始化数据接口。
* 这将一同初始化 ESP32 的 WIFI
*
* @return 0
*/
int socket_inet_init(void)
{
extern void socket_inet_server_init(void);
socket_inet_server_init();
return 0;
}

View File

@@ -0,0 +1,41 @@
/**
* @file socket_inet.h
* @author LokLiang
* @brief 主要把 sockets 标准接口封装为 sb_data_port.h::sb_data_port_t 接口
* @version 0.1
* @date 2023-11-10
*
* @copyright Copyright (c) 2023
*
*/
#pragma once
#include <netinet/in.h>
#include "drivers/data_port/sb_data_port.h"
#include "os/os.h"
typedef void *socket_listen_t;
typedef socket_listen_t socket_listen_tcp_t;
typedef void (*connect_cb)(bool is_connect, sb_data_port_t *port);
typedef void (*rx_event_cb)(sb_data_port_t *port);
typedef struct
{
uint16_t rx_buf_size; // 为该接口提供多大的接收缓存(建议取值 256..512,更多依赖协议栈的缓存)
rx_event_cb rx_event; // 当该接口收到数据时执行的回调函数,可取值为 NULL
os_work_t *rx_resume_work; // 当该接口收到数据时唤醒的工作项,可取值为 NULL
} socket_server_bind_t;
int socket_inet_init(void);
sb_data_port_t *socket_inet_server_bind_udp(uint16_t listen_port, const socket_server_bind_t *bind_param);
void socket_inet_server_unbind_udp(sb_data_port_t *port);
int socket_inet_server_udp_read_addr(sb_data_port_t *port, in_addr_t *s_addr, in_port_t *sin_port);
int socket_inet_server_udp_broadcast(sb_data_port_t *port, uint8_t ip_v4[4], uint16_t broadcast_port, const void *data, uint32_t size);
socket_listen_tcp_t socket_inet_server_listen_tcp(uint16_t listen_port, uint8_t tcp_backlog, const connect_cb connect);
sb_data_port_t *socket_inet_server_bind_tcp(socket_listen_tcp_t listen_tcp, const socket_server_bind_t *bind_param);
void socket_inet_server_unbind_tcp(socket_listen_tcp_t listen_tcp);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,265 @@
/**
* @file socket_inet_server_shell.c
* @author LokLiang
* @brief
* @version 0.1
* @date 2023-11-28
*
* @copyright Copyright (c) 2024
*
* 用于测试 socket 数据接口。
* 注意事项:
* 需要配合 wifi_shell 模块使用。
* 操作:
* 通过命令行,输入 inet open 打开连接,输入 wifi oa 或 wifi os 选择 wifi 模式;
* 在 wifi_shell.c::wifi_shell_register() 部分包含了连接信息,可根据这些信息连接或修改必要参数;
* 无线连接成功后,可通过工具测试发送和接收的速度等。
*/
#include "socket_inet_server_shell.h"
#include "socket_inet.h"
#include "shell/sh.h"
#include <string.h>
#include "os/os.h"
#include "drivers/data_port/sb_data_port.h"
#define CONFIG_SYS_LOG_LEVEL SYS_LOG_LEVEL_INF
#define SYS_LOG_DOMAIN "SH"
#include "sys_log.h"
static void _server_tcp_connect_cb(bool is_connect, sb_data_port_t *port);
static void _bind_and_open_tcp(uint8_t hdl_id);
static void _bind_and_open_udp(uint8_t hdl_id, uint16_t listen_port);
static void _unbind_and_close(uint8_t hdl_id);
static void _work_speed_handler(void *arg);
static void _work_read_handler(void *arg);
static struct
{
socket_listen_tcp_t tcp_listen;
struct
{
sb_data_port_t *data_port;
os_work_t work_hdl;
int stype; // 0: udp, 1: tcp
} hdl[4];
os_work_t s_speed_work_hdl;
int recv_size;
int err_size;
int s_recv_total_tcp;
int recv_total;
} s_cm;
SH_CMD_FN(_open);
SH_CMD_FN(_close);
SH_DEF_SUB_CMD(
sub_wifi,
SH_SETUP_CMD("open", "打开接口", _open, NULL), //
SH_SETUP_CMD("close", "关闭接口", _close, NULL), //
);
SH_DEF_CMD(
_register_tcp_wifi,
SH_SETUP_CMD("inet", "操作 WIFI 数据接口", NULL, sub_wifi), //
);
void socket_server_shell_register(void)
{
sh_register_cmd(&_register_tcp_wifi);
socket_inet_init();
os_work_create(&s_cm.s_speed_work_hdl, "work-speed", _work_speed_handler, NULL, OS_PRIORITY_LOWEST);
os_work_submit(default_os_work_q_hdl, &s_cm.s_speed_work_hdl, 0);
s_cm.tcp_listen = socket_inet_server_listen_tcp(4278, 2, _server_tcp_connect_cb);
}
void socket_server_shell_unregister(void)
{
sh_unregister_cmd(&_register_tcp_wifi);
}
static void _server_tcp_connect_cb(bool is_connect, sb_data_port_t *port)
{
SYS_LOG_INF("%s", is_connect ? "connected" : "disconnected");
if (is_connect)
{
os_thread_sleep(10);
sb_data_port_write(port, "hello\r\n", 7, 0);
}
}
static void _bind_and_open_tcp(uint8_t hdl_id)
{
SYS_ASSERT(hdl_id < __ARRAY_SIZE(s_cm.hdl), "");
if (s_cm.hdl[hdl_id].data_port == NULL)
{
socket_server_bind_t bind_param = {
.rx_buf_size = 0x1000,
.rx_event = NULL,
.rx_resume_work = &s_cm.hdl[hdl_id].work_hdl,
};
s_cm.hdl[hdl_id].data_port = socket_inet_server_bind_tcp(s_cm.tcp_listen, &bind_param);
s_cm.hdl[hdl_id].stype = 1;
}
if (s_cm.hdl[hdl_id].data_port)
{
sb_data_port_start(s_cm.hdl[hdl_id].data_port);
os_work_create(&s_cm.hdl[hdl_id].work_hdl, "work-read", _work_read_handler, s_cm.hdl[hdl_id].data_port, OS_PRIORITY_LOWEST);
os_work_submit(default_os_work_q_hdl, &s_cm.hdl[hdl_id].work_hdl, 0);
}
}
static void _bind_and_open_udp(uint8_t hdl_id, uint16_t listen_port)
{
SYS_ASSERT(hdl_id < __ARRAY_SIZE(s_cm.hdl), "");
if (s_cm.hdl[hdl_id].data_port)
{
return;
}
socket_server_bind_t bind_param = {
.rx_buf_size = 0x1000,
.rx_event = NULL,
.rx_resume_work = &s_cm.hdl[hdl_id].work_hdl,
};
s_cm.hdl[hdl_id].data_port = socket_inet_server_bind_udp(listen_port, &bind_param);
s_cm.hdl[hdl_id].stype = 0;
if (s_cm.hdl[hdl_id].data_port)
{
sb_data_port_start(s_cm.hdl[hdl_id].data_port);
os_work_create(&s_cm.hdl[hdl_id].work_hdl, "work-read", _work_read_handler, s_cm.hdl[hdl_id].data_port, OS_PRIORITY_LOWEST);
os_work_submit(default_os_work_q_hdl, &s_cm.hdl[hdl_id].work_hdl, 0);
}
}
static void _unbind_and_close(uint8_t hdl_id)
{
SYS_ASSERT(hdl_id < __ARRAY_SIZE(s_cm.hdl), "");
if (os_work_is_valid(&s_cm.hdl[hdl_id].work_hdl))
os_work_delete(&s_cm.hdl[hdl_id].work_hdl);
if (s_cm.hdl[hdl_id].data_port)
{
if (s_cm.hdl[hdl_id].stype == 0)
{
socket_inet_server_unbind_udp(s_cm.hdl[hdl_id].data_port);
s_cm.hdl[hdl_id].data_port = NULL;
}
else
{
sb_data_port_stop(s_cm.hdl[hdl_id].data_port);
}
}
}
static void _work_speed_handler(void *arg)
{
static os_time_t last_time;
os_time_t curr_time = os_get_sys_time();
int time_cost = curr_time - last_time;
bool recv_flag = false;
os_work_later(1000);
time_cost += !time_cost;
for (int i = 0; i < __ARRAY_SIZE(s_cm.hdl); i++)
{
sb_data_port_t *port = s_cm.hdl[i].data_port;
if (port && sb_data_port_is_started(port))
{
if (s_cm.recv_size)
{
int result = s_cm.recv_size * 1000 / time_cost;
s_cm.recv_total += s_cm.recv_size;
s_cm.recv_size = 0;
SYS_LOG_INF("val trans speed: %2u.%02u KiB/S, recv total: %d bytes", result / 0x400, result % 0x400 * 100 / 0x400, s_cm.recv_total);
if (s_cm.err_size)
{
SYS_LOG_DBG("err total: %d times", s_cm.err_size);
s_cm.err_size = 0;
}
recv_flag = true;
}
}
}
if (recv_flag == false)
{
s_cm.recv_total = 0;
}
last_time = curr_time;
}
static void _work_read_handler(void *arg)
{
sb_data_port_t *port = arg;
static uint8_t val_log = '0';
while (sb_data_port_is_started(port))
{
uint8_t buf[1500];
int r_size = sb_data_port_read(port, buf, sizeof(buf), 0);
if (r_size <= 0)
{
break;
}
else
{
sb_data_port_write(port, buf, r_size, 0);
s_cm.recv_size += r_size;
SYS_LOG_DUMP(buf, r_size, 0, 0);
for (int i = 0; i < r_size; i++)
{
if (buf[i] != val_log)
{
s_cm.err_size++;
val_log = buf[i];
}
val_log = '0' + (val_log - '0' + 1) % 10;
}
os_work_later(0);
}
}
}
SH_CMD_FN(_open)
{
_bind_and_open_udp(0, 14550);
_bind_and_open_udp(1, 14550 + 1);
_bind_and_open_tcp(2);
_bind_and_open_tcp(3);
return 0;
}
SH_CMD_FN(_close)
{
_unbind_and_close(0);
_unbind_and_close(1);
_unbind_and_close(2);
_unbind_and_close(3);
return 0;
}
/*
soc base free
wifi open
wifi close
*/

View File

@@ -0,0 +1,4 @@
#pragma once
void socket_server_shell_register(void);
void socket_server_shell_unregister(void);

View File

@@ -0,0 +1,405 @@
#include "wifi.h"
#include <netinet/in.h>
#include "esp_mac.h"
#include "esp_wifi.h"
#include "esp_netif_types.h"
#include "esp_err.h"
#define CONFIG_SYS_LOG_LEVEL SYS_LOG_LEVEL_INF
#define SYS_LOG_DOMAIN "WIFI"
#include "sys_log.h"
static struct
{
uint8_t init;
uint8_t curr_mode; // 0: 已关闭, 1: ap, 2: sta, 3: ap+sta
wifi_netif_mode_t cfg_mode;
wifi_init_t init_param;
esp_netif_t *netif;
uint8_t mac[6];
union
{
wifi_ap_connect_status_t ap_status;
wifi_sta_connect_status_t sta_status;
};
} s_cm;
static void _wifi_start_ap(void);
static void _wifi_start_sta(void);
static void _wiri_stop_ap(void);
static void _wiri_stop_sta(void);
static void _wifi_event_handler_ap(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data); // 由 _wifi_start_ap() 启动时设置的事件回调函数,处理 AP 模式下客户端的连接状态
static void _wifi_event_handler_sta(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data); // 由 _wifi_start_sta() 启动时设置的事件回调函数,处理 STA 模式下的连接状态
/**
* @brief 初始化设置。可重复设置
*
* @param init_struct
*/
void wifi_netif_init(wifi_init_t *init_struct)
{
if (s_cm.init == 0)
{
s_cm.init = 1;
ESP_ERROR_CHECK(esp_netif_init());
}
s_cm.init_param = *init_struct;
}
/**
* @brief 设置 WIFI 模式。在下次执行 wifi_start() 时根据此模式启动 WIFI
*
* @param mode @ref wifi_netif_mode_t
*/
void wifi_set_mode(wifi_netif_mode_t mode)
{
s_cm.cfg_mode = mode;
}
void wifi_start(void)
{
switch (s_cm.cfg_mode)
{
case WIFI_NETIF_MODE_AP:
_wifi_start_ap();
break;
case WIFI_NETIF_MODE_STA:
default:
_wifi_start_sta();
break;
}
}
/**
* @brief 关闭 WIFI
*
*/
void wifi_stop(void)
{
if (s_cm.curr_mode == 0)
{
SYS_LOG_WRN("wifi has been stoped");
return;
}
if (s_cm.curr_mode == 1)
{
_wiri_stop_ap();
}
else if (s_cm.curr_mode == 2)
{
_wiri_stop_sta();
}
s_cm.curr_mode = 0;
}
/**
* @brief (仅在 AP 模式下)获取已连接的工作站信息
*
* @param netif_sta_list
* @return int
*/
int wifi_get_sta_list(wifi_sta_mac_ip_list_t *netif_sta_list)
{
wifi_sta_list_t sta_list;
memset(&sta_list, 0, sizeof(sta_list));
memset(netif_sta_list, 0, sizeof(wifi_sta_mac_ip_list_t));
esp_err_t err = esp_wifi_ap_get_sta_list(&sta_list);
if (err != ESP_OK)
{
return err;
}
return esp_wifi_ap_get_sta_list_with_ip(&sta_list, netif_sta_list);
}
/**
* @brief (仅在 AP 模式下)获取已连接的 AP 信息
*
* @param netif_ap[out]
* @return int
*/
int wifi_get_ap_info(esp_netif_ip_info_t *netif_ap)
{
if (s_cm.curr_mode == 2)
{
return esp_netif_get_ip_info(s_cm.netif, netif_ap);
}
return -1;
}
/**
* @brief 初始化 WIFI 协议栈,启动 WIFI 的 AP 模式,启动 DHCP 服务
*
*/
static void _wifi_start_ap(void)
{
if (s_cm.curr_mode == 1)
{
SYS_LOG_WRN("wifi has been started");
return;
}
if (s_cm.curr_mode)
{
wifi_stop();
}
s_cm.curr_mode = 1;
// Initialize networking stack
ESP_ERROR_CHECK(esp_event_loop_create_default());
// start the DHCP server
if (s_cm.netif == NULL)
{
s_cm.netif = esp_netif_create_default_wifi_ap();
assert(s_cm.netif);
// stop DHCP server
ESP_ERROR_CHECK(esp_netif_dhcps_stop(s_cm.netif));
// assign a static IP to the network interface
esp_netif_ip_info_t info;
memset(&info, 0, sizeof(info));
IP4_ADDR(&info.ip, s_cm.init_param.ap.ip_v4[0], s_cm.init_param.ap.ip_v4[1], s_cm.init_param.ap.ip_v4[2], s_cm.init_param.ap.ip_v4[3]);
IP4_ADDR(&info.gw, s_cm.init_param.ap.gw_v4[0], s_cm.init_param.ap.gw_v4[1], s_cm.init_param.ap.gw_v4[2], s_cm.init_param.ap.gw_v4[3]); // ESP acts as router, so gw addr will be its own addr
IP4_ADDR(&info.netmask, s_cm.init_param.ap.mask_v4[0], s_cm.init_param.ap.mask_v4[1], s_cm.init_param.ap.mask_v4[2], s_cm.init_param.ap.mask_v4[3]);
ESP_ERROR_CHECK(esp_netif_set_ip_info(s_cm.netif, &info));
ESP_ERROR_CHECK(esp_netif_dhcps_start(s_cm.netif));
}
/* Initialise ESP32 in SoftAP curr_mode */
const char *ssid = s_cm.init_param.ap.ssid;
const char *password = s_cm.init_param.ap.password;
wifi_config_t wifi_config;
memset(&wifi_config, 0, sizeof(wifi_config_t));
memcpy(wifi_config.ap.ssid, ssid, strlen(ssid));
wifi_config.ap.ssid_len = strlen(ssid);
wifi_config.ap.max_connection = s_cm.init_param.ap.max_connection;
if (strlen(password) == 0)
{
wifi_config.ap.authmode = WIFI_AUTH_OPEN;
}
else
{
strcpy((char *)wifi_config.ap.password, password);
wifi_config.ap.authmode = WIFI_AUTH_WPA_WPA2_PSK;
}
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, _wifi_event_handler_ap, NULL));
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_AP, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_start());
wifi_ap_connect_cb connect_cb = s_cm.init_param.ap.connect_cb;
if (connect_cb)
{
s_cm.ap_status = WIFI_AP_CONNECT_GOT_STA;
connect_cb(s_cm.ap_status, 0);
}
SYS_LOG_INF("done");
}
/**
* @brief 初始化 WIFI 协议栈,启动 WIFI 的 STA 模式
*
*/
static void _wifi_start_sta(void)
{
if (s_cm.curr_mode == 2)
{
SYS_LOG_WRN("wifi has been started");
return;
}
if (s_cm.curr_mode)
{
wifi_stop();
}
s_cm.curr_mode = 2;
/* 参考自 examples/wifi/fast_scan/main/fast_scan.c */
ESP_ERROR_CHECK(esp_event_loop_create_default());
// Initialize default station as network interface instance (esp-netif)
if (s_cm.netif == NULL)
{
s_cm.netif = esp_netif_create_default_wifi_sta();
assert(s_cm.netif);
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &_wifi_event_handler_sta, s_cm.netif, NULL));
ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &_wifi_event_handler_sta, s_cm.netif, NULL));
}
// Initialize and start WiFi
const char *ssid = s_cm.init_param.sta.ssid;
const char *password = s_cm.init_param.sta.password;
wifi_config_t wifi_config;
memset(&wifi_config, 0, sizeof(wifi_config_t));
strncpy((char *)wifi_config.sta.ssid, ssid, sizeof(wifi_config.sta.ssid));
strncpy((char *)wifi_config.sta.password, password, sizeof(wifi_config.sta.password));
wifi_config.sta.scan_method = WIFI_FAST_SCAN;
wifi_config.sta.sort_method = WIFI_CONNECT_AP_BY_SIGNAL;
wifi_config.sta.threshold.rssi = -127;
wifi_config.sta.threshold.authmode = WIFI_AUTH_OPEN;
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_start());
wifi_sta_connect_cb connect_cb = s_cm.init_param.sta.connect_cb;
if (connect_cb)
{
uint8_t ip_v4[4];
memset(ip_v4, 0, sizeof(ip_v4));
s_cm.sta_status = WIFI_STA_CONNECT_CONNECTING;
connect_cb(s_cm.sta_status, ip_v4);
}
SYS_LOG_INF("done");
}
static void _wiri_stop_ap(void)
{
/* Deinitialise ESP32 netif */
ESP_ERROR_CHECK(esp_wifi_stop());
if (s_cm.netif)
{
esp_netif_dhcp_status_t status;
ESP_ERROR_CHECK(esp_netif_dhcps_get_status(s_cm.netif, &status));
if (ESP_NETIF_DHCP_STARTED == status)
{
ESP_ERROR_CHECK(esp_netif_dhcps_stop(s_cm.netif));
}
esp_netif_destroy_default_wifi(s_cm.netif);
s_cm.netif = NULL;
}
ESP_ERROR_CHECK(esp_wifi_deinit());
// Deinitialize networking stack
ESP_ERROR_CHECK(esp_event_loop_delete_default());
wifi_ap_connect_cb connect_cb = s_cm.init_param.ap.connect_cb;
if (connect_cb)
{
s_cm.ap_status = WIFI_AP_CONNECT_STOPED;
connect_cb(s_cm.ap_status, 0);
}
SYS_LOG_INF("done");
s_cm.curr_mode = 0;
}
static void _wiri_stop_sta(void)
{
/* Deinitialise ESP32 netif */
ESP_ERROR_CHECK(esp_wifi_stop());
if (s_cm.netif)
{
esp_netif_destroy_default_wifi(s_cm.netif);
s_cm.netif = NULL;
}
ESP_ERROR_CHECK(esp_wifi_deinit());
// Deinitialize networking stack
ESP_ERROR_CHECK(esp_event_loop_delete_default());
wifi_sta_connect_cb connect_cb = s_cm.init_param.sta.connect_cb;
if (connect_cb)
{
uint8_t ip_v4[4];
memset(ip_v4, 0, sizeof(ip_v4));
s_cm.sta_status = WIFI_STA_CONNECT_STOPED;
connect_cb(s_cm.sta_status, ip_v4);
}
SYS_LOG_INF("done");
s_cm.curr_mode = 0;
}
static void _wifi_event_handler_ap(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data)
{
switch (event_id)
{
case WIFI_EVENT_AP_STACONNECTED:
{
wifi_event_ap_staconnected_t *event = (wifi_event_ap_staconnected_t *)event_data;
SYS_LOG_INF("station " MACSTR " join, AID=%d",
MAC2STR(event->mac), event->aid);
memcpy(s_cm.mac, event->mac, 6);
break;
}
case WIFI_EVENT_AP_STADISCONNECTED:
{
wifi_event_ap_stadisconnected_t *event = (wifi_event_ap_stadisconnected_t *)event_data;
SYS_LOG_INF("station " MACSTR " leave, AID=%d",
MAC2STR(event->mac), event->aid);
break;
}
default:
return;
}
wifi_ap_connect_cb connect_cb = s_cm.init_param.ap.connect_cb;
if (connect_cb)
{
wifi_sta_mac_ip_list_t netif_sta_list;
wifi_get_sta_list(&netif_sta_list);
s_cm.ap_status = WIFI_AP_CONNECT_GOT_STA;
connect_cb(s_cm.ap_status, netif_sta_list.num);
}
}
void get_wifi_mac(uint8_t *mac)
{
memcpy(mac, s_cm.mac, 6);
}
static void _wifi_event_handler_sta(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data)
{
wifi_sta_connect_status_t status;
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START)
{
status = WIFI_STA_CONNECT_CONNECTING;
esp_wifi_connect();
}
else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED)
{
status = WIFI_STA_CONNECT_CONNECTING;
esp_wifi_connect();
}
else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP)
{
status = WIFI_STA_CONNECT_GOT_IP;
ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
SYS_LOG_INF("got ip: " IPSTR, IP2STR(&event->ip_info.ip));
}
else
{
return;
}
wifi_sta_connect_cb connect_cb = s_cm.init_param.sta.connect_cb;
if (connect_cb)
{
uint8_t ip_v4[4];
memset(ip_v4, 0, sizeof(ip_v4));
if (s_cm.sta_status != status)
{
s_cm.sta_status = status;
connect_cb(s_cm.sta_status, ip_v4);
}
}
}

View File

@@ -0,0 +1,78 @@
/**
* @file wifi.h
* @author LokLiang
* @brief 操作 ESP32 WIFI 的两种基本模式的开关
* @version 0.1
* @date 2023-11-24
*
* @copyright Copyright (c) 2023
*
*/
#pragma once
#include <stdint.h>
#include "esp_wifi_ap_get_sta_list.h"
typedef enum
{
WIFI_AP_CONNECT_STOPED,
WIFI_AP_CONNECT_GOT_STA,
} wifi_ap_connect_status_t;
typedef enum
{
WIFI_STA_CONNECT_STOPED,
WIFI_STA_CONNECT_CONNECTING,
WIFI_STA_CONNECT_GOT_IP,
} wifi_sta_connect_status_t;
/**
* @brief AP 模式下的连接状态回调函数。
* 提示:可使用 wifi_get_sta_list() 读出所有已连接的客户端信息
*/
typedef void (*wifi_ap_connect_cb)(wifi_ap_connect_status_t status, uint8_t connect_cnt);
/**
* @brief STA 模式下的连接状态回调函数。
*/
typedef void (*wifi_sta_connect_cb)(wifi_sta_connect_status_t status, uint8_t ip_v4[4]);
typedef struct
{
struct
{
char ssid[33]; /**< SSID of soft-AP. If ssid_len field is 0, this must be a Null terminated string. Otherwise, length is set according to ssid_len. */
char password[65]; /**< Password of soft-AP. */
uint8_t ip_v4[4];
uint8_t gw_v4[4];
uint8_t mask_v4[4];
uint8_t max_connection; // 最大连接数
wifi_ap_connect_cb connect_cb;
} ap;
struct
{
char ssid[33];
char password[65];
wifi_sta_connect_cb connect_cb;
} sta;
} wifi_init_t;
typedef enum
{
WIFI_NETIF_MODE_AP,
WIFI_NETIF_MODE_STA,
} wifi_netif_mode_t;
void wifi_netif_init(wifi_init_t *init_struct);
void wifi_set_mode(wifi_netif_mode_t mode);
void wifi_start(void);
void wifi_stop(void);
int wifi_get_sta_list(wifi_sta_mac_ip_list_t *netif_sta_list);
int wifi_get_ap_info(esp_netif_ip_info_t *netif_ap);
void get_wifi_mac(uint8_t *mac);

View File

@@ -0,0 +1,82 @@
#include "wifi_shell.h"
#include "wifi.h"
#include "shell/sh.h"
#include <string.h>
#include "os/os.h"
#define CONFIG_SYS_LOG_LEVEL SYS_LOG_LEVEL_INF
#define SYS_LOG_DOMAIN "SH"
#include "sys_log.h"
SH_CMD_FN(_open_ap);
SH_CMD_FN(_open_sta);
SH_CMD_FN(_close);
SH_DEF_SUB_CMD(
sub_wifi,
SH_SETUP_CMD("oa", "打开 wifi ap 模式", _open_ap, NULL), //
SH_SETUP_CMD("os", "打开 wifi sta 模式", _open_sta, NULL), //
SH_SETUP_CMD("close", "关闭 wifi", _close, NULL), //
);
SH_DEF_CMD(
_register_tcp_wifi,
SH_SETUP_CMD("wifi", "操作 WIFI 接口", NULL, sub_wifi), //
);
void wifi_shell_register(void)
{
sh_register_cmd(&_register_tcp_wifi);
/* 初始化 WIFI */
wifi_init_t init_struct = {
.ap = {
.ssid = "wifi-test", /**< SSID of soft-AP. If ssid_len field is 0, this must be a Null terminated string. Otherwise, length is set according to ssid_len. */
.password = "12345678", /**< Password of soft-AP. */
.ip_v4 = {192, 168, 1, 1},
.gw_v4 = {192, 168, 1, 1},
.mask_v4 = {255, 255, 255, 0},
.max_connection = 1,
.connect_cb = NULL,
},
.sta = {
#if 0
.ssid = "KFXJ",
.password = "Kfdx201*",
#else
.ssid = "SDWAN",
.password = "Dxltkj201",
#endif
.connect_cb = NULL,
},
};
wifi_netif_init(&init_struct);
wifi_set_mode(WIFI_NETIF_MODE_STA);
}
void wifi_shell_unregister(void)
{
sh_unregister_cmd(&_register_tcp_wifi);
}
SH_CMD_FN(_open_ap)
{
wifi_set_mode(WIFI_NETIF_MODE_AP);
wifi_start();
return 0;
}
SH_CMD_FN(_open_sta)
{
wifi_set_mode(WIFI_NETIF_MODE_STA);
wifi_start();
return 0;
}
SH_CMD_FN(_close)
{
wifi_stop();
return 0;
}

View File

@@ -0,0 +1,4 @@
#pragma once
void wifi_shell_register(void);
void wifi_shell_unregister(void);