diff --git a/README.md b/README.md index ebf99f6..c1b792c 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Networked bedside clock utilising an ESP32-SOLO-1. - [x] Snooze and dismiss buttons - [x] Multiple alarms - [x] Alarm conditions (e.g. weekday / weekend) -- [ ] IPv6 support +- [x] IPv6 support ## Firmware diff --git a/components/wifi/wifi.c b/components/wifi/wifi.c index 9996192..6bcf5fc 100644 --- a/components/wifi/wifi.c +++ b/components/wifi/wifi.c @@ -17,12 +17,35 @@ #define TAG "Wifi" +#define CONFIG_MAX_IPV6_ADDRS 5 + static wifi_config_t config; static WifiStatus status; static unsigned retries; -static esp_netif_ip_info_t ip_info; +static bool have_ipv4; +static esp_netif_ip_info_t ipv4; +static esp_ip6_addr_t ipv6_addrs[CONFIG_MAX_IPV6_ADDRS]; +static unsigned ipv6_count; static esp_netif_t *net_if; +static const char *ipv6_type_str(esp_ip6_addr_t *addr) +{ + switch (esp_netif_ip6_get_addr_type(addr)) { + case ESP_IP6_ADDR_IS_GLOBAL: + return "Global"; + case ESP_IP6_ADDR_IS_LINK_LOCAL: + return "Link local"; + case ESP_IP6_ADDR_IS_SITE_LOCAL: + return "Site local"; + case ESP_IP6_ADDR_IS_UNIQUE_LOCAL: + return "Unique local"; + case ESP_IP6_ADDR_IS_IPV4_MAPPED_IPV6: + return "IPv4 mapped"; + default: + return "Unknown:"; + } +} + static void wifi_event_handler( void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) @@ -39,6 +62,12 @@ static void wifi_event_handler( ESP_LOGE(TAG, "Error connecting to WiFi: %04x", error); break; + case WIFI_EVENT_STA_CONNECTED: + error = esp_netif_create_ip6_linklocal(net_if); + if (error != ESP_OK) + ESP_LOGE(TAG, "Error creating IPv6 address"); + break; + case WIFI_EVENT_STA_DISCONNECTED: if (retries < CONFIG_WIFI_MAX_RETRIES) { ESP_LOGI(TAG, "Retrying connection"); @@ -53,7 +82,7 @@ static void wifi_event_handler( break; default: - ESP_LOGD(TAG, "Unhandled WiFi event: %ld", event_id); + ESP_LOGI(TAG, "Unhandled WiFi event: %ld", event_id); break; } } @@ -65,16 +94,34 @@ static void got_ip_event_handler( (void)arg; (void)event_base; - if (event_id != IP_EVENT_STA_GOT_IP) { - ESP_LOGW(TAG, "Unexpected IP event received: %ld", event_id); - return; + switch (event_id) { + case IP_EVENT_STA_GOT_IP: { + ip_event_got_ip_t *got_ip_data = (ip_event_got_ip_t *)event_data; + memcpy(&ipv4, &got_ip_data->ip_info, sizeof(ipv4)); + have_ipv4 = true; + ESP_LOGI(TAG, "Got IPv4 address " IPSTR, IP2STR(&ipv4.ip)); + status = WIFI_STATUS_CONNECTED; + break; } - ip_event_got_ip_t *got_ip_data = (ip_event_got_ip_t *)event_data; - memcpy(&ip_info, &got_ip_data->ip_info, sizeof(ip_info)); + case IP_EVENT_GOT_IP6: { + ip_event_got_ip6_t *got_ip6_data = (ip_event_got_ip6_t *)event_data; + memcpy( + &ipv6_addrs[ipv6_count], &got_ip6_data->ip6_info.ip, + sizeof(esp_ip6_addr_t)); + ESP_LOGI( + TAG, "Got IPv6 address " IPV6STR " (%s)", + IPV62STR(ipv6_addrs[ipv6_count]), + ipv6_type_str(&ipv6_addrs[ipv6_count])); + ++ipv6_count; + status = WIFI_STATUS_CONNECTED; + break; + } - ESP_LOGI(TAG, "Got IP " IPSTR, IP2STR(&ip_info.ip)); - status = WIFI_STATUS_CONNECTED; + default: + ESP_LOGI(TAG, "Unhandled IP event received: %ld", event_id); + break; + } } static void handle_hostname_update(const char *hostname) @@ -135,8 +182,25 @@ static int command_func(int argc, char **argv) } else if (strcmp(argv[1], "reconnect") == 0) { wifi_reconnect(); return 0; - } else if (strcmp(argv[1], "ip") == 0) { - printf(IPSTR "\n", IP2STR(&ip_info.ip)); + } else if (strcmp(argv[1], "ipv4") == 0) { + if (!have_ipv4) { + printf("IPv4 not configured\n"); + return 1; + } + printf(IPSTR "\n", IP2STR(&ipv4.ip)); + printf("Netmask: " IPSTR "\n", IP2STR(&ipv4.netmask)); + printf("Gateway: " IPSTR "\n", IP2STR(&ipv4.gw)); + return 0; + } else if (strcmp(argv[1], "ipv6") == 0) { + if (ipv6_count == 0) { + printf("IPv6 not configured\n"); + return 1; + } + for (unsigned i = 0; i < ipv6_count; ++i) { + printf( + "%-12s " IPV6STR "\n", ipv6_type_str(&ipv6_addrs[i]), + IPV62STR(ipv6_addrs[i])); + } return 0; } else { printf("Subcommand not recognised\n"); @@ -149,6 +213,8 @@ void wifi_init(void) esp_err_t error; status = WIFI_STATUS_DISCONNECTED; + have_ipv4 = false; + ipv6_count = 0; error = esp_netif_init(); if (error != ESP_OK) { @@ -178,8 +244,7 @@ void wifi_init(void) return; } error = esp_event_handler_instance_register( - IP_EVENT, IP_EVENT_STA_GOT_IP, &got_ip_event_handler, NULL, - &instance); + IP_EVENT, ESP_EVENT_ANY_ID, &got_ip_event_handler, NULL, &instance); if (error != ESP_OK) { ESP_LOGE(TAG, "Error registering IP event handler: %04x", error); return; @@ -222,8 +287,8 @@ void wifi_init(void) settings_add_psk_callback(&handle_psk_update); console_register( - "wifi", "Manage WiFi connection", "wifi ", - command_func); + "wifi", "Manage WiFi connection", + "wifi ", command_func); } void wifi_reconnect(void)