diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 16a4732..f9fd813 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -155,7 +155,6 @@ before_script: .build_homekit_switch: &build_homekit_switch # Building homekit_switch app - Started - cd $CI_PROJECT_DIR/examples/homekit_switch -- mkdir components - cd components - echo Cloning esp-homekit-sdk - git clone --recursive --branch master --depth 1 https://github.com/espressif/esp-homekit-sdk.git diff --git a/examples/homekit_switch/components/app_wifi/CMakeLists.txt b/examples/homekit_switch/components/app_wifi/CMakeLists.txt new file mode 100644 index 0000000..e382faa --- /dev/null +++ b/examples/homekit_switch/components/app_wifi/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRCS "app_wifi_with_homekit.c" + INCLUDE_DIRS "." + REQUIRES wifi_provisioning qrcode esp_hap_core esp_hap_platform) diff --git a/examples/homekit_switch/components/app_wifi/Kconfig.projbuild b/examples/homekit_switch/components/app_wifi/Kconfig.projbuild new file mode 100644 index 0000000..8a7ce7b --- /dev/null +++ b/examples/homekit_switch/components/app_wifi/Kconfig.projbuild @@ -0,0 +1,35 @@ +menu "App Wi-Fi Provisioning" + + config APP_WIFI_PROV_SHOW_QR + bool "Show provisioning QR code" + default y + help + Show the QR code for provisioning. + + choice APP_WIFI_PROV_TRANSPORT + bool "Provisioning Transport method" + default APP_WIFI_PROV_TRANSPORT_BLE + help + Wi-Fi provisioning component offers both, SoftAP and BLE transports. Choose any one. + + config APP_WIFI_PROV_TRANSPORT_SOFTAP + bool "Soft AP" + config APP_WIFI_PROV_TRANSPORT_BLE + bool "BLE" + select BT_ENABLED + depends on IDF_TARGET_ESP32 || IDF_TARGET_ESP32C3 + endchoice + + config APP_WIFI_PROV_TRANSPORT + int + default 1 if APP_WIFI_PROV_TRANSPORT_SOFTAP + default 2 if APP_WIFI_PROV_TRANSPORT_BLE + + config APP_WIFI_USE_WAC_PROVISIONING + bool "Apple WAC Provisioning" + depends on HAP_MFI_ENABLE + default n + help + "Use Apple WAC Provisioning" + +endmenu diff --git a/examples/homekit_switch/main/app_wifi_with_homekit.c b/examples/homekit_switch/components/app_wifi/app_wifi_with_homekit.c similarity index 75% rename from examples/homekit_switch/main/app_wifi_with_homekit.c rename to examples/homekit_switch/components/app_wifi/app_wifi_with_homekit.c index 49c831e..81cd5f6 100644 --- a/examples/homekit_switch/main/app_wifi_with_homekit.c +++ b/examples/homekit_switch/components/app_wifi/app_wifi_with_homekit.c @@ -35,7 +35,11 @@ #include #include #include -#include "app_wifi.h" +#include "app_wifi_with_homekit.h" + +#ifdef CONFIG_APP_WIFI_USE_WAC_PROVISIONING +#include +#endif /* CONFIG_APP_WIFI_USE_WAC_PROVISIONING */ static const char *TAG = "app_wifi"; static const int WIFI_CONNECTED_EVENT = BIT0; @@ -67,6 +71,28 @@ static void app_wifi_print_qr(const char *name, const char *pop, const char *tra ESP_LOGI(TAG, "If QR code is not visible, copy paste the below URL in a browser.\n%s?data=%s", QRCODE_BASE_URL, payload); } +#ifdef CONFIG_APP_WIFI_USE_WAC_PROVISIONING +#ifdef CONFIG_APP_WIFI_PROV_TRANSPORT_SOFTAP +static void app_wac_softap_start(char *ssid) +{ +} +#else +static void app_wac_softap_start(char *ssid) +{ + hap_wifi_softap_start(ssid); +} +#endif /* ! CONFIG_APP_WIFI_PROV_TRANSPORT_SOFTAP */ +static void app_wac_softap_stop(void) +{ + hap_wifi_softap_stop(); +} +static void app_wac_sta_connect(wifi_config_t *wifi_cfg) +{ + wifi_prov_mgr_configure_sta(wifi_cfg); +} +#endif /* CONFIG_APP_WIFI_USE_WAC_PROVISIONING */ + + /* Event handler for catching system events */ static void event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) @@ -96,6 +122,9 @@ static void event_handler(void* arg, esp_event_base_t event_base, ESP_LOGI(TAG, "Provisioning successful"); break; case WIFI_PROV_END: +#ifdef CONFIG_APP_WIFI_USE_WAC_PROVISIONING + hap_wac_stop(); +#endif /* De-initialize manager once provisioning is finished */ wifi_prov_mgr_deinit(); break; @@ -104,14 +133,42 @@ static void event_handler(void* arg, esp_event_base_t event_base, } } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) { esp_wifi_connect(); + } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_CONNECTED) { +#ifdef ESP_NETIF_SUPPORTED + esp_netif_create_ip6_linklocal((esp_netif_t *)arg); +#else + tcpip_adapter_create_ip6_linklocal(TCPIP_ADAPTER_IF_STA); +#endif } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data; ESP_LOGI(TAG, "Connected with IP Address:" IPSTR, IP2STR(&event->ip_info.ip)); /* Signal main application to continue execution */ xEventGroupSetBits(wifi_event_group, WIFI_CONNECTED_EVENT); + } 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; + ESP_LOGI(TAG, "Connected with IPv6 Address:" IPV6STR, IPV62STR(event->ip6_info.ip)); } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) { ESP_LOGI(TAG, "Disconnected. Connecting to the AP again..."); esp_wifi_connect(); +#ifdef CONFIG_APP_WIFI_USE_WAC_PROVISIONING + } else if (event_base == HAP_WAC_EVENT) { + switch (event_id) { + case HAP_WAC_EVENT_REQ_SOFTAP_START: + app_wac_softap_start((char *)event_data); + break; + case HAP_WAC_EVENT_REQ_SOFTAP_STOP: + app_wac_softap_stop(); + break; + case HAP_WAC_EVENT_RECV_CRED: + app_wac_sta_connect((wifi_config_t *)event_data); + break; + case HAP_WAC_EVENT_STOPPED: + ESP_LOGI(TAG, "WAC Stopped"); + break; + default: + break; + } +#endif /* CONFIG_APP_WIFI_USE_WAC_PROVISIONING */ } } @@ -120,45 +177,55 @@ static void wifi_init_sta() ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); ESP_ERROR_CHECK(esp_wifi_start()); } - -static void get_device_service_name(char *service_name, size_t max) -{ - uint8_t eth_mac[6]; - const char *ssid_prefix = "PROV_"; - esp_wifi_get_mac(WIFI_IF_STA, eth_mac); - snprintf(service_name, max, "%s%02X%02X%02X", - ssid_prefix, eth_mac[3], eth_mac[4], eth_mac[5]); -} - -/* free the return value after use. */ -static char *read_random_bytes_from_nvs() +/* Free random_bytes after use only if function returns ESP_OK */ +static esp_err_t read_random_bytes_from_nvs(uint8_t **random_bytes, size_t *len) { nvs_handle handle; esp_err_t err; - size_t required_size = 0; - void *value; + *len = 0; if ((err = nvs_open_from_partition(CONFIG_ESP_RMAKER_FACTORY_PARTITION_NAME, CREDENTIALS_NAMESPACE, NVS_READONLY, &handle)) != ESP_OK) { ESP_LOGD(TAG, "NVS open for %s %s %s failed with error %d", CONFIG_ESP_RMAKER_FACTORY_PARTITION_NAME, CREDENTIALS_NAMESPACE, RANDOM_NVS_KEY, err); - return NULL; + return ESP_FAIL; } - if ((err = nvs_get_blob(handle, RANDOM_NVS_KEY, NULL, &required_size)) != ESP_OK) { - ESP_LOGD(TAG, "Failed to read key %s with error %d size %d", RANDOM_NVS_KEY, err, required_size); + if ((err = nvs_get_blob(handle, RANDOM_NVS_KEY, NULL, len)) != ESP_OK) { + ESP_LOGD(TAG, "Error %d. Failed to read key %s.", err, RANDOM_NVS_KEY); nvs_close(handle); - return NULL; + return ESP_ERR_NOT_FOUND; } - value = calloc(required_size + 1, 1); /* + 1 for NULL termination */ - if (value) { - nvs_get_blob(handle, RANDOM_NVS_KEY, value, &required_size); + *random_bytes = calloc(*len, 1); + if (*random_bytes) { + nvs_get_blob(handle, RANDOM_NVS_KEY, *random_bytes, len); + nvs_close(handle); + return ESP_OK; } - nvs_close(handle); - return value; + return ESP_ERR_NO_MEM; } +static esp_err_t get_device_service_name(char *service_name, size_t max) +{ + uint8_t *nvs_random = NULL; + const char *ssid_prefix = "PROV_"; + size_t nvs_random_size = 0; + if ((read_random_bytes_from_nvs(&nvs_random, &nvs_random_size) != ESP_OK) || nvs_random_size < 3) { + uint8_t eth_mac[6]; + esp_wifi_get_mac(WIFI_IF_STA, eth_mac); + snprintf(service_name, max, "%s%02x%02x%02x", ssid_prefix, eth_mac[3], eth_mac[4], eth_mac[5]); + } else { + snprintf(service_name, max, "%s%02x%02x%02x", ssid_prefix, nvs_random[nvs_random_size - 3], + nvs_random[nvs_random_size - 2], nvs_random[nvs_random_size - 1]); + } + if (nvs_random) { + free(nvs_random); + } + return ESP_OK; +} + + static esp_err_t get_device_pop(char *pop, size_t max, app_wifi_pop_type_t pop_type) { if (!pop || !max) { @@ -175,14 +242,13 @@ static esp_err_t get_device_pop(char *pop, size_t max, app_wifi_pop_type_t pop_t return err; } } else if (pop_type == POP_TYPE_RANDOM) { - char *nvs_pop = read_random_bytes_from_nvs(); - if (!nvs_pop) { + uint8_t *nvs_random; + size_t nvs_random_size = 0; + if ((read_random_bytes_from_nvs(&nvs_random, &nvs_random_size) != ESP_OK) || nvs_random_size < 4) { return ESP_ERR_NOT_FOUND; } else { - strncpy(pop, nvs_pop, max - 1); - pop[max - 1] = 0; - free(nvs_pop); - nvs_pop = NULL; + snprintf(pop, max, "%02x%02x%02x%02x", nvs_random[0], nvs_random[1], nvs_random[2], nvs_random[3]); + free(nvs_random); return ESP_OK; } } else { @@ -203,15 +269,21 @@ void app_wifi_with_homekit_init(void) ESP_ERROR_CHECK(esp_event_loop_create_default()); wifi_event_group = xEventGroupCreate(); - /* Register our event handler for Wi-Fi, IP and Provisioning related events */ - ESP_ERROR_CHECK(esp_event_handler_register(WIFI_PROV_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL)); - ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL)); - ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL)); - /* Initialize Wi-Fi including netif with default config */ #ifdef ESP_NETIF_SUPPORTED - esp_netif_create_default_wifi_sta(); + esp_netif_t *wifi_netif = esp_netif_create_default_wifi_sta(); #endif + + /* Register our event handler for Wi-Fi, IP and Provisioning related events */ +#ifdef ESP_NETIF_SUPPORTED + ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, wifi_netif)); +#else + ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL)); +#endif + ESP_ERROR_CHECK(esp_event_handler_register(WIFI_PROV_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL)); + ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL)); + ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_GOT_IP6, &event_handler, NULL)); + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK(esp_wifi_init(&cfg)); } @@ -326,6 +398,10 @@ esp_err_t app_wifi_with_homekit_start(app_wifi_pop_type_t pop_type) app_wifi_print_qr(service_name, pop, PROV_TRANSPORT_SOFTAP); #endif /* CONFIG_APP_WIFI_PROV_TRANSPORT_BLE */ ESP_LOGI(TAG, "Provisioning Started. Name : %s, POP : %s", service_name, pop); +#ifdef CONFIG_APP_WIFI_USE_WAC_PROVISIONING + esp_event_handler_register(HAP_WAC_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL); + hap_wac_start(); +#endif /* CONFIG_APP_WIFI_USE_WAC_PROVISIONING */ } else { ESP_LOGI(TAG, "Already provisioned, starting Wi-Fi STA"); diff --git a/examples/homekit_switch/main/app_wifi_with_homekit.h b/examples/homekit_switch/components/app_wifi/app_wifi_with_homekit.h similarity index 100% rename from examples/homekit_switch/main/app_wifi_with_homekit.h rename to examples/homekit_switch/components/app_wifi/app_wifi_with_homekit.h diff --git a/examples/homekit_switch/components/app_wifi/component.mk b/examples/homekit_switch/components/app_wifi/component.mk new file mode 100644 index 0000000..2ec0e78 --- /dev/null +++ b/examples/homekit_switch/components/app_wifi/component.mk @@ -0,0 +1,2 @@ +COMPONENT_ADD_INCLUDEDIRS := . +COMPONENT_SRCDIRS := . diff --git a/examples/homekit_switch/main/CMakeLists.txt b/examples/homekit_switch/main/CMakeLists.txt index d0e57db..71aa1a8 100644 --- a/examples/homekit_switch/main/CMakeLists.txt +++ b/examples/homekit_switch/main/CMakeLists.txt @@ -1,2 +1,2 @@ -idf_component_register(SRCS ./app_driver.c ./app_main.c ./app_homekit.c ./app_wifi_with_homekit.c +idf_component_register(SRCS ./app_driver.c ./app_main.c ./app_homekit.c INCLUDE_DIRS ".") diff --git a/examples/homekit_switch/main/app_homekit.c b/examples/homekit_switch/main/app_homekit.c index aab362b..a93b401 100644 --- a/examples/homekit_switch/main/app_homekit.c +++ b/examples/homekit_switch/main/app_homekit.c @@ -173,6 +173,7 @@ esp_err_t app_homekit_start(bool init_state) app_homekit_show_qr(); } #endif + hap_enable_mfi_auth(HAP_MFI_AUTH_HW); /* Register our event handler for Wi-Fi, IP and Provisioning related events */ esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &app_homekit_event_handler, NULL); esp_event_handler_register(HAP_EVENT, HAP_EVENT_CTRL_UNPAIRED, &app_homekit_event_handler, NULL);