From 83fcfe6e4c534ec7773886fef64cf2a02a7f5f45 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Thu, 3 Oct 2024 09:52:14 +0200 Subject: [PATCH 1/4] feat(ethernet_init): Add support for Ethernet inialization --- examples/smart_outlet/main/app_main.c | 60 +++++++++++++++++++- examples/smart_outlet/main/idf_component.yml | 17 ++++++ 2 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 examples/smart_outlet/main/idf_component.yml diff --git a/examples/smart_outlet/main/app_main.c b/examples/smart_outlet/main/app_main.c index 89b8629..37df898 100644 --- a/examples/smart_outlet/main/app_main.c +++ b/examples/smart_outlet/main/app_main.c @@ -38,6 +38,12 @@ #include #include +#include "esp_netif.h" +#include "esp_eth.h" +#include "esp_event.h" +#include "esp_log.h" +#include "ethernet_init.h" +#include "sdkconfig.h" static const char *TAG = "HAP outlet"; @@ -45,7 +51,7 @@ static const char *TAG = "HAP outlet"; #define SMART_OUTLET_TASK_STACKSIZE 4 * 1024 #define SMART_OUTLET_TASK_NAME "hap_outlet" -#define OUTLET_IN_USE_GPIO GPIO_NUM_0 +#define OUTLET_IN_USE_GPIO GPIO_NUM_4 #define ESP_INTR_FLAG_DEFAULT 0 @@ -127,6 +133,53 @@ static int outlet_write(hap_write_data_t write_data[], int count, return ret; } +static void got_ip_event_handler(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data) +{ + ip_event_got_ip_t *event = (ip_event_got_ip_t *) event_data; + const esp_netif_ip_info_t *ip_info = &event->ip_info; + + ESP_LOGI(TAG, "Ethernet Got IP Address"); + ESP_LOGI(TAG, "~~~~~~~~~~~"); + ESP_LOGI(TAG, "IP: " IPSTR, IP2STR(&ip_info->ip)); + ESP_LOGI(TAG, "MASK: " IPSTR, IP2STR(&ip_info->netmask)); + ESP_LOGI(TAG, "GW: " IPSTR, IP2STR(&ip_info->gw)); + ESP_LOGI(TAG, "~~~~~~~~~~~"); +} + +void eth_init(void) +{ + uint8_t eth_port_cnt = 0; + esp_eth_handle_t *eth_handles; + + // Initialize TCP/IP network interface aka the esp-netif (should be called only once in application) + ESP_ERROR_CHECK(esp_netif_init()); + // Create default event loop that running in background + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + // Initialize Ethernet driver + ESP_ERROR_CHECK(ethernet_init_all(ð_handles, ð_port_cnt)); + + if (eth_port_cnt != 1) { + ESP_LOGE(TAG, "Error: Only one Ethernet instance is supported in this example"); + abort(); + } + + // Use ESP_NETIF_DEFAULT_ETH when just one Ethernet interface is used and you don't need to modify + // default esp-netif configuration parameters. + esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH(); + esp_netif_t *eth_netif = esp_netif_new(&cfg); + // Attach Ethernet driver to TCP/IP stack + ESP_ERROR_CHECK(esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handles[0]))); + + // Register user defined event handers + ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL)); + + // Start Ethernet driver state machine + ESP_ERROR_CHECK(esp_eth_start(eth_handles[0])); +} + + /*The main thread for handling the Smart Outlet Accessory */ static void smart_outlet_thread_entry(void *p) { @@ -206,12 +259,13 @@ static void smart_outlet_thread_entry(void *p) hap_enable_mfi_auth(HAP_MFI_AUTH_HW); /* Initialize Wi-Fi */ - app_wifi_init(); + // app_wifi_init(); + eth_init(); /* After all the initializations are done, start the HAP core */ hap_start(); /* Start Wi-Fi */ - app_wifi_start(portMAX_DELAY); + // app_wifi_start(portMAX_DELAY); uint32_t io_num = OUTLET_IN_USE_GPIO; hap_val_t appliance_value = { diff --git a/examples/smart_outlet/main/idf_component.yml b/examples/smart_outlet/main/idf_component.yml new file mode 100644 index 0000000..941202b --- /dev/null +++ b/examples/smart_outlet/main/idf_component.yml @@ -0,0 +1,17 @@ +## IDF Component Manager Manifest File +dependencies: + espressif/ethernet_init: "^0.3.1" + ## Required IDF version + idf: + version: ">=4.1.0" + # # Put list of dependencies here + # # For components maintained by Espressif: + # component: "~1.0.0" + # # For 3rd party components: + # username/component: ">=1.0.0,<2.0.0" + # username2/component2: + # version: "~1.0.0" + # # For transient dependencies `public` flag can be set. + # # `public` flag doesn't have an effect dependencies of the `main` component. + # # All dependencies of `main` are public by default. + # public: true From 48b930bbb25065a54225bd720b2a86d7b76c3213 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 11 Oct 2024 10:52:15 +0200 Subject: [PATCH 2/4] fix(pairing): Remove pairing timer requirements --- .../homekit/esp_hap_core/src/esp_hap_pair_setup.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/components/homekit/esp_hap_core/src/esp_hap_pair_setup.c b/components/homekit/esp_hap_core/src/esp_hap_pair_setup.c index a96fb1b..4a87d9a 100644 --- a/components/homekit/esp_hap_core/src/esp_hap_pair_setup.c +++ b/components/homekit/esp_hap_core/src/esp_hap_pair_setup.c @@ -74,13 +74,13 @@ static void hap_pairing_mode_timeout(TimerHandle_t handle) void hap_start_pairing_mode_timer(void) { - if (!hap_priv.pairing_mode_timer) { - hap_priv.pairing_mode_timer = xTimerCreate("hap_pairing_mode_timer", HAP_PAIRING_MODE_TIMEOUT_IN_TICKS, - pdFALSE, NULL, hap_pairing_mode_timeout); - } - if (hap_priv.pairing_mode_timer) { - xTimerStart(hap_priv.pairing_mode_timer, 0); - } + // if (!hap_priv.pairing_mode_timer) { + // hap_priv.pairing_mode_timer = xTimerCreate("hap_pairing_mode_timer", HAP_PAIRING_MODE_TIMEOUT_IN_TICKS, + // pdFALSE, NULL, hap_pairing_mode_timeout); + // } + // if (hap_priv.pairing_mode_timer) { + // xTimerStart(hap_priv.pairing_mode_timer, 0); + // } } void hap_stop_pairing_mode_timer(void) From 4a17a28da92113fa76a1fbaf2861e23bbb56009c Mon Sep 17 00:00:00 2001 From: David Cermak Date: Thu, 24 Oct 2024 20:26:48 +0200 Subject: [PATCH 3/4] fix(mdns): Use custom netif with custom actions --- examples/smart_outlet/main/app_main.c | 55 +++++++++++++++++++----- examples/smart_outlet/sdkconfig.defaults | 24 ++++------- 2 files changed, 53 insertions(+), 26 deletions(-) diff --git a/examples/smart_outlet/main/app_main.c b/examples/smart_outlet/main/app_main.c index 37df898..75e2795 100644 --- a/examples/smart_outlet/main/app_main.c +++ b/examples/smart_outlet/main/app_main.c @@ -43,6 +43,7 @@ #include "esp_event.h" #include "esp_log.h" #include "ethernet_init.h" +#include "mdns.h" #include "sdkconfig.h" static const char *TAG = "HAP outlet"; @@ -133,18 +134,49 @@ static int outlet_write(hap_write_data_t write_data[], int count, return ret; } -static void got_ip_event_handler(void *arg, esp_event_base_t event_base, +static void start_probing(void *ctx) +{ + esp_netif_t* esp_netif = (esp_netif_t*)ctx; + vTaskDelay((2 * 1000) / portTICK_PERIOD_MS); + ESP_LOGI(TAG, "MDNS_EVENT_ENABLE_IP4"); + if (mdns_netif_action(esp_netif, MDNS_EVENT_ENABLE_IP4) != ESP_OK) { + // this is still okay, as the netif might have been deinit in the meantime + ESP_LOGW(TAG, "Failed to run mdns action: MDNS_EVENT_ENABLE_IP4"); + } + vTaskDelete(NULL); +} + +static void event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) { - ip_event_got_ip_t *event = (ip_event_got_ip_t *) event_data; - const esp_netif_ip_info_t *ip_info = &event->ip_info; - - ESP_LOGI(TAG, "Ethernet Got IP Address"); - ESP_LOGI(TAG, "~~~~~~~~~~~"); - ESP_LOGI(TAG, "IP: " IPSTR, IP2STR(&ip_info->ip)); - ESP_LOGI(TAG, "MASK: " IPSTR, IP2STR(&ip_info->netmask)); - ESP_LOGI(TAG, "GW: " IPSTR, IP2STR(&ip_info->gw)); - ESP_LOGI(TAG, "~~~~~~~~~~~"); + static esp_netif_t *s_netif = NULL; + if (event_base == IP_EVENT) { + ip_event_got_ip_t *event = (ip_event_got_ip_t *) event_data; + const esp_netif_ip_info_t *ip_info = &event->ip_info; + if (s_netif == NULL) { + // expect mdns has been initialized already + s_netif = event->esp_netif; + ESP_ERROR_CHECK(mdns_register_netif(s_netif)); + } + + ESP_LOGI(TAG, "Ethernet Got IP Address"); + ESP_LOGI(TAG, "~~~~~~~~~~~"); + ESP_LOGI(TAG, "IP: " IPSTR, IP2STR(&ip_info->ip)); + ESP_LOGI(TAG, "MASK: " IPSTR, IP2STR(&ip_info->netmask)); + ESP_LOGI(TAG, "GW: " IPSTR, IP2STR(&ip_info->gw)); + ESP_LOGI(TAG, "~~~~~~~~~~~"); + if (s_netif) { + ESP_LOGI(TAG, "MDNS probing starts in 2 seconds..."); + xTaskCreate(start_probing, "start_probes", 4096, s_netif, 5, NULL); + } + } else if (event_base == ETH_EVENT) { + ESP_LOGI(TAG, "Ethernet disconnected"); + if (s_netif) { + ESP_LOGW(TAG, "MDNS_EVENT_DISABLE_IP4"); + ESP_ERROR_CHECK(mdns_netif_action(s_netif, MDNS_EVENT_DISABLE_IP4 )); + s_netif = NULL; + } + } } void eth_init(void) @@ -173,7 +205,8 @@ void eth_init(void) ESP_ERROR_CHECK(esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handles[0]))); // Register user defined event handers - ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL)); + ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, event_handler, NULL)); // -> to start mDNS probing + ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_DISCONNECTED, event_handler, NULL)); // -> to notify mDNS to stop // Start Ethernet driver state machine ESP_ERROR_CHECK(esp_eth_start(eth_handles[0])); diff --git a/examples/smart_outlet/sdkconfig.defaults b/examples/smart_outlet/sdkconfig.defaults index b1bdab3..600e20a 100644 --- a/examples/smart_outlet/sdkconfig.defaults +++ b/examples/smart_outlet/sdkconfig.defaults @@ -1,23 +1,17 @@ +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_hap.csv" -CONFIG_PARTITION_TABLE_CUSTOM_APP_BIN_OFFSET=0x10000 +CONFIG_BT_ENABLED=y +CONFIG_BT_NIMBLE_ENABLED=y CONFIG_FREERTOS_UNICORE=y -CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=n -CONFIG_FREERTOS_ASSERT_FAIL_ABORT=n -CONFIG_FREERTOS_ASSERT_DISABLE=y CONFIG_LWIP_MAX_SOCKETS=16 -CONFIG_LWIP_SO_REUSE=y +CONFIG_LWIP_AUTOIP=y +CONFIG_LWIP_AUTOIP_RATE_LIMIT_INTERVAL=60 CONFIG_LWIP_MAX_ACTIVE_TCP=12 CONFIG_LWIP_MAX_LISTENING_TCP=12 CONFIG_LWIP_UDP_RECVMBOX_SIZE=10 -CONFIG_MBEDTLS_HARDWARE_MPI=y CONFIG_MBEDTLS_HARDWARE_SHA=n -CONFIG_ESP_TASK_WDT=n -CONFIG_LWIP_AUTOIP=y -CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y -CONFIG_LWIP_AUTOIP_RATE_LIMIT_INTERVAL=60 -CONFIG_MP_BLOB_SUPPORT=y -CONFIG_ENABLE_UNIFIED_PROVISIONING=y -CONFIG_BT_ENABLED=y -CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y -CONFIG_BT_NIMBLE_ENABLED=y \ No newline at end of file +CONFIG_MDNS_MAX_INTERFACES=1 +CONFIG_MDNS_PREDEF_NETIF_STA=n +CONFIG_MDNS_PREDEF_NETIF_AP=n +CONFIG_MDNS_PREDEF_NETIF_ETH=n From 04e9f4d14836f03675e86b37e6a6ae8af0af3920 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 8 Nov 2024 07:49:48 +0100 Subject: [PATCH 4/4] feat(ipv6): Add support for IPv6 on custom eth netif --- examples/smart_outlet/main/app_main.c | 51 +++++++++++++++++---------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/examples/smart_outlet/main/app_main.c b/examples/smart_outlet/main/app_main.c index 75e2795..e5fce3c 100644 --- a/examples/smart_outlet/main/app_main.c +++ b/examples/smart_outlet/main/app_main.c @@ -134,23 +134,13 @@ static int outlet_write(hap_write_data_t write_data[], int count, return ret; } -static void start_probing(void *ctx) -{ - esp_netif_t* esp_netif = (esp_netif_t*)ctx; - vTaskDelay((2 * 1000) / portTICK_PERIOD_MS); - ESP_LOGI(TAG, "MDNS_EVENT_ENABLE_IP4"); - if (mdns_netif_action(esp_netif, MDNS_EVENT_ENABLE_IP4) != ESP_OK) { - // this is still okay, as the netif might have been deinit in the meantime - ESP_LOGW(TAG, "Failed to run mdns action: MDNS_EVENT_ENABLE_IP4"); - } - vTaskDelete(NULL); -} +static esp_netif_t *eth_netif = NULL; static void event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) { static esp_netif_t *s_netif = NULL; - if (event_base == IP_EVENT) { + if (event_base == IP_EVENT && event_id == IP_EVENT_ETH_GOT_IP) { ip_event_got_ip_t *event = (ip_event_got_ip_t *) event_data; const esp_netif_ip_info_t *ip_info = &event->ip_info; if (s_netif == NULL) { @@ -166,14 +156,37 @@ static void event_handler(void *arg, esp_event_base_t event_base, ESP_LOGI(TAG, "GW: " IPSTR, IP2STR(&ip_info->gw)); ESP_LOGI(TAG, "~~~~~~~~~~~"); if (s_netif) { - ESP_LOGI(TAG, "MDNS probing starts in 2 seconds..."); - xTaskCreate(start_probing, "start_probes", 4096, s_netif, 5, NULL); + ESP_LOGI(TAG, "MDNS probing on IPv4 starting"); + if (mdns_netif_action(s_netif, MDNS_EVENT_ENABLE_IP4) != ESP_OK) { + // this is still okay, as the netif might have been deinit in the meantime + ESP_LOGW(TAG, "Failed to run mdns action: MDNS_EVENT_ENABLE_IP4"); + } + } + } else if (event_base == IP_EVENT && event_id == IP_EVENT_GOT_IP6) { + ip_event_got_ip6_t *event = (ip_event_got_ip6_t *)event_data; + if (s_netif == NULL) { + // expect mdns has been initialized already + s_netif = event->esp_netif; + ESP_ERROR_CHECK(mdns_register_netif(s_netif)); + } + esp_ip6_addr_type_t ipv6_type = esp_netif_ip6_get_addr_type(&event->ip6_info.ip); + ESP_LOGI(TAG, "Got IPv6 event: Interface \"%s\" address: " IPV6STR ", type: %d", esp_netif_get_desc(event->esp_netif), + IPV62STR(event->ip6_info.ip), (int)ipv6_type); + if (s_netif) { + ESP_LOGI(TAG, "MDNS probing on IPv6 starting"); + if (mdns_netif_action(s_netif, MDNS_EVENT_ENABLE_IP6) != ESP_OK) { + // this is still okay, as the netif might have been deinit in the meantime + ESP_LOGW(TAG, "Failed to run mdns action: MDNS_EVENT_ENABLE_IP6"); + } } - } else if (event_base == ETH_EVENT) { + } else if (event_base == ETH_EVENT && event_id == ETHERNET_EVENT_CONNECTED) { + ESP_LOGI(TAG, "Ethernet connected"); + ESP_ERROR_CHECK(esp_netif_create_ip6_linklocal(eth_netif)); + } else if (event_base == ETH_EVENT && event_id == ETHERNET_EVENT_DISCONNECTED) { ESP_LOGI(TAG, "Ethernet disconnected"); if (s_netif) { - ESP_LOGW(TAG, "MDNS_EVENT_DISABLE_IP4"); - ESP_ERROR_CHECK(mdns_netif_action(s_netif, MDNS_EVENT_DISABLE_IP4 )); + ESP_LOGW(TAG, "MDNS_EVENT_DISABLE_IP4 and IP4"); + ESP_ERROR_CHECK(mdns_netif_action(s_netif, MDNS_EVENT_DISABLE_IP4 | MDNS_EVENT_DISABLE_IP6 )); s_netif = NULL; } } @@ -200,13 +213,15 @@ void eth_init(void) // Use ESP_NETIF_DEFAULT_ETH when just one Ethernet interface is used and you don't need to modify // default esp-netif configuration parameters. esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH(); - esp_netif_t *eth_netif = esp_netif_new(&cfg); + eth_netif = esp_netif_new(&cfg); // Attach Ethernet driver to TCP/IP stack ESP_ERROR_CHECK(esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handles[0]))); // Register user defined event handers ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, event_handler, NULL)); // -> to start mDNS probing + ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_GOT_IP6, event_handler, NULL)); // -> to start mDNS probing ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_DISCONNECTED, event_handler, NULL)); // -> to notify mDNS to stop + ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_CONNECTED, event_handler, NULL)); // -> to notify mDNS to stop // Start Ethernet driver state machine ESP_ERROR_CHECK(esp_eth_start(eth_handles[0]));