如何在 ESP32 上正确设置 TCP/IP 适配器的主机名
How to correctly set the hostname for the TCP/IP adapter on the ESP32
问题
Espressif 的 ESP-32(在本例中为 ESP-WROOM-32)出现在具有默认主机名 "Espressif" 的网络上。我不想使用这个主机名,所以我选择按如下方式更改它:
// Initialize the TCP/IP adapter (launches handler task)
tcpip_adapter_init();
// Set the hostname for the default TCP/IP station interface
if ((err = tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA, g_hostname))
!= ESP_OK) {
return err;
}
当然,这是行不通的。我收到以下错误:ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY
。
尝试的解决方案
为了解决这个问题,我查看 TCP/IP 适配器在完成初始化后是否会 post 某种事件。这样我就可以注册一个处理程序来设置主机名。这里的 Espressif WiFi Driver Guide 表示启动了一个任务 - 所以可能有一个事件吧:
"The main task calls tcpip_adapter_init() to create an LwIP core task and initialize LwIP-related work."
嗯,我找不到任何此类事件。 API documentation 和实际文件本身 (tcpip_adapter.h
) 都没有。我检查了头文件中的事件,none 似乎只是为了指示 TCP/IP 适配器已完成启动而存在 :
/** IP event declarations */
typedef enum {
IP_EVENT_STA_GOT_IP, /*!< ESP32 station got IP from connected AP */
IP_EVENT_STA_LOST_IP, /*!< ESP32 station lost IP and the IP is reset to 0 */
IP_EVENT_AP_STAIPASSIGNED, /*!< ESP32 soft-AP assign an IP to a connected station */
IP_EVENT_GOT_IP6, /*!< ESP32 station or ap or ethernet interface v6IP addr is preferred */
IP_EVENT_ETH_GOT_IP, /*!< ESP32 ethernet got IP from connected AP */
} ip_event_t;
可能的线索
我注意到,在 Espressif's WiFi guide 中,它们表示事件 SYSTEM_EVENT_STA_START
(表示站已经开始)将:
Upon receiving this event, the event task will initialize the LwIP network interface (netif).
如果我在处理程序收到此事件后发出调用,我将不再收到错误:
// After the event WIFI_EVENT_STA_START
if (base == WIFI_EVENT && id == WIFI_EVENT_STA_START) {
// Set the hostname for the default TCP/IP station interface
if ((err = tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA, g_hostname))
!= ESP_OK) {
fprintf(stderr, "Err: %s", esp_err_to_name(err));
}
...
}
但是,主机名仍然没有改变。因此我发现自己有点卡住了。我怎样才能真正改变主机名?我搜索这个问题几乎没有发现任何结果。然而,esp32 是一个流行的模块,我相信很多其他人会发现自己面临同样的问题。
事实证明我做对了。是我的路由器未能充分刷新主机名。为了保持一致性,我将重申我为解决此问题所做的工作:
Espressif WiFi Guide表示事件SYSTEM_EVENT_STA_START
生成一次esp_wifi_start()
returns成功。
这个事件的产生也意味着事件任务将初始化LwIP网络接口(netif)。因为我们知道 TCP/IP 适配器此时肯定已经初始化,所以我们可以调用主机名更改函数。这是一个执行此操作的处理程序示例,直接取自他们的示例:
void wifi_event_handler (void *handler_arg, esp_event_base_t base, int32_t id,
void *event_data) {
esp_err_t err;
// If esp_wifi_start() returned ESP_OK and WiFi mode is in station mode
if (base == WIFI_EVENT && id == WIFI_EVENT_STA_START) {
const char *name;
// Set the hostname for the default TCP/IP station interface
if ((err = tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA, g_hostname))
!= ESP_OK) {
fprintf(stderr, "Err: %s", esp_err_to_name(err));
} else {
if ((err = tcpip_adapter_get_hostname(TCPIP_ADAPTER_IF_STA, &name)) != ESP_OK) {
fprintf(stderr, "Err Get Hostname: %s\n", esp_err_to_name(err));
} else {
printf("Hostname: %s\n", (name == NULL ? "<None>" : name));
}
}
...
}
...
}
在这个例子中,我在设置后获取主机名,并将其打印到stdout
。如果您是 运行 ESP32 的监视器,则可以验证它。主机名集将是路由器页面上可见的主机名。
问题
Espressif 的 ESP-32(在本例中为 ESP-WROOM-32)出现在具有默认主机名 "Espressif" 的网络上。我不想使用这个主机名,所以我选择按如下方式更改它:
// Initialize the TCP/IP adapter (launches handler task)
tcpip_adapter_init();
// Set the hostname for the default TCP/IP station interface
if ((err = tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA, g_hostname))
!= ESP_OK) {
return err;
}
当然,这是行不通的。我收到以下错误:ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY
。
尝试的解决方案
为了解决这个问题,我查看 TCP/IP 适配器在完成初始化后是否会 post 某种事件。这样我就可以注册一个处理程序来设置主机名。这里的 Espressif WiFi Driver Guide 表示启动了一个任务 - 所以可能有一个事件吧:
"The main task calls tcpip_adapter_init() to create an LwIP core task and initialize LwIP-related work."
嗯,我找不到任何此类事件。 API documentation 和实际文件本身 (tcpip_adapter.h
) 都没有。我检查了头文件中的事件,none 似乎只是为了指示 TCP/IP 适配器已完成启动而存在 :
/** IP event declarations */
typedef enum {
IP_EVENT_STA_GOT_IP, /*!< ESP32 station got IP from connected AP */
IP_EVENT_STA_LOST_IP, /*!< ESP32 station lost IP and the IP is reset to 0 */
IP_EVENT_AP_STAIPASSIGNED, /*!< ESP32 soft-AP assign an IP to a connected station */
IP_EVENT_GOT_IP6, /*!< ESP32 station or ap or ethernet interface v6IP addr is preferred */
IP_EVENT_ETH_GOT_IP, /*!< ESP32 ethernet got IP from connected AP */
} ip_event_t;
可能的线索
我注意到,在 Espressif's WiFi guide 中,它们表示事件 SYSTEM_EVENT_STA_START
(表示站已经开始)将:
Upon receiving this event, the event task will initialize the LwIP network interface (netif).
如果我在处理程序收到此事件后发出调用,我将不再收到错误:
// After the event WIFI_EVENT_STA_START
if (base == WIFI_EVENT && id == WIFI_EVENT_STA_START) {
// Set the hostname for the default TCP/IP station interface
if ((err = tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA, g_hostname))
!= ESP_OK) {
fprintf(stderr, "Err: %s", esp_err_to_name(err));
}
...
}
但是,主机名仍然没有改变。因此我发现自己有点卡住了。我怎样才能真正改变主机名?我搜索这个问题几乎没有发现任何结果。然而,esp32 是一个流行的模块,我相信很多其他人会发现自己面临同样的问题。
事实证明我做对了。是我的路由器未能充分刷新主机名。为了保持一致性,我将重申我为解决此问题所做的工作:
Espressif WiFi Guide表示事件SYSTEM_EVENT_STA_START
生成一次esp_wifi_start()
returns成功。
这个事件的产生也意味着事件任务将初始化LwIP网络接口(netif)。因为我们知道 TCP/IP 适配器此时肯定已经初始化,所以我们可以调用主机名更改函数。这是一个执行此操作的处理程序示例,直接取自他们的示例:
void wifi_event_handler (void *handler_arg, esp_event_base_t base, int32_t id,
void *event_data) {
esp_err_t err;
// If esp_wifi_start() returned ESP_OK and WiFi mode is in station mode
if (base == WIFI_EVENT && id == WIFI_EVENT_STA_START) {
const char *name;
// Set the hostname for the default TCP/IP station interface
if ((err = tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA, g_hostname))
!= ESP_OK) {
fprintf(stderr, "Err: %s", esp_err_to_name(err));
} else {
if ((err = tcpip_adapter_get_hostname(TCPIP_ADAPTER_IF_STA, &name)) != ESP_OK) {
fprintf(stderr, "Err Get Hostname: %s\n", esp_err_to_name(err));
} else {
printf("Hostname: %s\n", (name == NULL ? "<None>" : name));
}
}
...
}
...
}
在这个例子中,我在设置后获取主机名,并将其打印到stdout
。如果您是 运行 ESP32 的监视器,则可以验证它。主机名集将是路由器页面上可见的主机名。