我正在尝试编写一个函数,该函数将使用 ssid、密码、通道和最大连接设备数来初始化 WLAN AP。下面是我的代码。
void wifi_init_softap(const char * ssid, const char *password, uint8_t channel, uint8_t max_conn)
{
ESP_ERROR_CHECK(esp_netif_init()); // Initialise ESP Netif, Which manages the DHCP Server
ESP_ERROR_CHECK(esp_event_loop_create_default()); // Create new event loop
// esp_netif_create_default_wifi_ap();
esp_netif_t *p_netif = esp_netif_create_default_wifi_ap(); // Create Default Wifi AP
esp_netif_ip_info_t ipInfo; // Stores IP & Gateway & Netmask
// Assignes default values to ip stack
IP4_ADDR(&ipInfo.ip, 192, 168, 1, 1);
IP4_ADDR(&ipInfo.gw, 192, 168, 1, 1);
IP4_ADDR(&ipInfo.netmask, 255, 255, 255, 0);
// Stop DHCP Server on p_netif, assign the new IP stack, and restart it
esp_netif_dhcps_stop(p_netif);
esp_netif_set_ip_info(p_netif, &ipInfo);
esp_netif_dhcps_start(p_netif);
//----------------------------------------------------------------------------------------//
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
ESP_EVENT_ANY_ID,
&wifi_event_handler,
NULL,
NULL));
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
//----------------------------------------------------------------------------------------//
// uint8_t *buffer_ssid = (uint8_t *)malloc((strlen(ssid)) * sizeof(char)+1);
// memcpy(buffer_ssid, ssid, (strlen(ssid)) * sizeof(char) );
wifi_config_t wifi_config = {
.ap = {
.ssid = "*ssid",
.ssid_len = strlen(ssid),
.channel = channel,
.password = "(*password)",
.max_connection = max_conn,
.authmode = WIFI_AUTH_WPA_WPA2_PSK},
};
if (strlen(password) == 0)
{
wifi_config.ap.authmode = WIFI_AUTH_OPEN;
}
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_start());
ESP_LOGI(TAG, "wifi_init_softap finished. SSID:%s password:%s channel:%d",
ssid, password, max_conn);
}
问题出在以下部分:
wifi_config_t wifi_config = {
.ap = {
.ssid = "*ssid",
.ssid_len = strlen(ssid),
.channel = channel,
.password = "(*password)",
.max_connection = max_conn,
.authmode = WIFI_AUTH_WPA_WPA2_PSK},
};
当我像上面那样将 ssid 和 passord 作为字符串常量传递时,它可以正确编译和运行。但是,如果我尝试将它们作为变量传递来初始化 wifi_config.ap.ssid,如下所示,它会输出一个我无法理解的错误。
代码:
wifi_config_t wifi_config = {
.ap = {
.ssid = *ssid,
.ssid_len = strlen(ssid),
.channel = channel,
.password = *password,
.max_connection = max_conn,
.authmode = WIFI_AUTH_WPA_WPA2_PSK},
};
错误信息:
missing braces around initializer [-Werror=missing-braces]
我无法想出解决方案。在“esp_wifi_types.h”中,可以找到 wifi_ap_config_t 的成员变量类型,如下所示。
typedef struct {
uint8_t ssid[32]; /**< SSID of ESP32 soft-AP. If ssid_len field is 0, this must be a Null terminated string. Otherwise, length is set according to ssid_len. */
uint8_t password[64]; /**< Password of ESP32 soft-AP. */
uint8_t ssid_len; /**< Optional length of SSID field. */
uint8_t channel; /**< Channel of ESP32 soft-AP */
wifi_auth_mode_t authmode; /**< Auth mode of ESP32 soft-AP. Do not support AUTH_WEP in soft-AP mode */
uint8_t ssid_hidden; /**< Broadcast SSID or not, default 0, broadcast the SSID */
uint8_t max_connection; /**< Max number of stations allowed to connect in, default 4, max 10 */
uint16_t beacon_interval; /**< Beacon interval which should be multiples of 100. Unit: TU(time unit, 1 TU = 1024 us). Range: 100 ~ 60000. Default value: 100 */
wifi_cipher_type_t pairwise_cipher; /**< pairwise cipher of SoftAP, group cipher will be derived using this. cipher values are valid starting from WIFI_CIPHER_TYPE_TKIP, enum values before that will be considered as invalid and default cipher suites(TKIP+CCMP) will be used. Valid cipher suites in softAP mode are WIFI_CIPHER_TYPE_TKIP, WIFI_CIPHER_TYPE_CCMP and WIFI_CIPHER_TYPE_TKIP_CCMP. */
bool ftm_responder; /**< Enable FTM Responder mode */
} wifi_ap_config_t;
由于
ssid
的 wifi_config_t
字段是一个数组,而您的 ssid
函数参数是一个指针,因此您不能将后者分配给前者。您需要的是将指针指向的数据复制到数组。如果您的 SSID 是一个以 null 结尾的字符串,那么您应该可以使用 strlcpy
函数来做到这一点,如下所示:
// destination first, source second, max size of buffer last
strlcpy(wifi_config.ap.ssid, ssid, 32);
如果
strlcpy
不可用,您可能需要使用 strncpy
代替,尽管 strlcpy
如果可用的话应该使用,因为它保证以空终止目标数组中的字符串。如果两者都不可用,则需要使用 ssid
函数手动查找 strlen
指向的字符串的长度,然后使用 memcpy
将这么多字节从 ssid
复制到 wifi_config.ap.ssid
,类似于strlcpy
是如何完成的:
size_t ssid_length = strlen(ssid);
memcpy(wifi_config.ap.ssid, ssid, ssid_length);
再次强调,这一切都假设
ssid
指针指向的字符串以 null 结尾。如果不是,您需要其他方法来找出 SSID 字符串的长度。
这是因为赋值
=
不适用于数组。您现在正在使用的值得注意的例外是常量字符串的分配。如果将常量字符串分配给数组,某些编译器会自动将其转换为 memcpy
调用。但是,它不适用于非常量字符串,例如 ssid
指针。在这种情况下,编译器尝试将指针的值(字符串的地址,类似于整数的值)分配给 uint8_t
数组。可以理解的是,该操作没有意义,因此编译器会抛出错误。
strlcopy 和 strncopy 都不适合我,因为编译器抱怨符号性。我诉诸于字节复制:
for (k=0; k<strlen(ssid); k++)
{
wifi_config.ap.ssid[k] = ssid[k];
}