| /* |
| * |
| * Copyright (c) 2018 Nest Labs, Inc. |
| * All rights reserved. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| /** |
| * @file |
| * General utility methods for the ESP32 platform. |
| */ |
| |
| #include <Weave/DeviceLayer/internal/WeaveDeviceLayerInternal.h> |
| |
| #include <Weave/DeviceLayer/ESP32/ESP32Utils.h> |
| |
| #include "esp_event.h" |
| #include "esp_wifi.h" |
| |
| using namespace ::nl::Weave::DeviceLayer::Internal; |
| using namespace ::nl::Weave::Profiles::NetworkProvisioning; |
| |
| WEAVE_ERROR ESP32Utils::IsAPEnabled(bool & apEnabled) |
| { |
| WEAVE_ERROR err; |
| wifi_mode_t curWiFiMode; |
| |
| err = esp_wifi_get_mode(&curWiFiMode); |
| if (err != ESP_OK) |
| { |
| WeaveLogError(DeviceLayer, "esp_wifi_get_mode() failed: %s", nl::ErrorStr(err)); |
| return err; |
| } |
| |
| apEnabled = (curWiFiMode == WIFI_MODE_AP || curWiFiMode == WIFI_MODE_APSTA); |
| |
| return WEAVE_NO_ERROR; |
| } |
| |
| bool ESP32Utils::IsStationProvisioned(void) |
| { |
| wifi_config_t stationConfig; |
| return (esp_wifi_get_config(ESP_IF_WIFI_STA, &stationConfig) == ERR_OK && stationConfig.sta.ssid[0] != 0); |
| } |
| |
| WEAVE_ERROR ESP32Utils::IsStationConnected(bool & connected) |
| { |
| wifi_ap_record_t apInfo; |
| connected = (esp_wifi_sta_get_ap_info(&apInfo) == ESP_OK); |
| return WEAVE_NO_ERROR; |
| } |
| |
| WEAVE_ERROR ESP32Utils::StartWiFiLayer(void) |
| { |
| WEAVE_ERROR err; |
| int8_t ignored; |
| bool wifiStarted; |
| |
| // There appears to be no direct way to ask the ESP WiFi layer if esp_wifi_start() |
| // has been called. So use the ESP_ERR_WIFI_NOT_STARTED error returned by |
| // esp_wifi_get_max_tx_power() to detect this. |
| err = esp_wifi_get_max_tx_power(&ignored); |
| switch (err) |
| { |
| case ESP_OK: |
| wifiStarted = true; |
| break; |
| case ESP_ERR_WIFI_NOT_STARTED: |
| wifiStarted = false; |
| err = ESP_OK; |
| break; |
| default: |
| ExitNow(); |
| } |
| |
| if (!wifiStarted) |
| { |
| WeaveLogProgress(DeviceLayer, "Starting ESP WiFi layer"); |
| |
| err = esp_wifi_start(); |
| if (err != ESP_OK) |
| { |
| WeaveLogError(DeviceLayer, "esp_wifi_start() failed: %s", nl::ErrorStr(err)); |
| } |
| } |
| |
| exit: |
| return err; |
| } |
| |
| WEAVE_ERROR ESP32Utils::EnableStationMode(void) |
| { |
| WEAVE_ERROR err; |
| wifi_mode_t curWiFiMode; |
| |
| // Get the current ESP WiFI mode. |
| err = esp_wifi_get_mode(&curWiFiMode); |
| if (err != ESP_OK) |
| { |
| WeaveLogError(DeviceLayer, "esp_wifi_get_mode() failed: %s", nl::ErrorStr(err)); |
| } |
| SuccessOrExit(err); |
| |
| // If station mode is not already enabled (implying the current mode is WIFI_MODE_AP), change |
| // the mode to WIFI_MODE_APSTA. |
| if (curWiFiMode == WIFI_MODE_AP) |
| { |
| WeaveLogProgress(DeviceLayer, "Changing ESP WiFi mode: %s -> %s", WiFiModeToStr(WIFI_MODE_AP), WiFiModeToStr(WIFI_MODE_APSTA)); |
| |
| err = esp_wifi_set_mode(WIFI_MODE_APSTA); |
| if (err != ESP_OK) |
| { |
| WeaveLogError(DeviceLayer, "esp_wifi_set_mode() failed: %s", nl::ErrorStr(err)); |
| } |
| SuccessOrExit(err); |
| } |
| |
| exit: |
| return err; |
| } |
| |
| WEAVE_ERROR ESP32Utils::SetAPMode(bool enabled) |
| { |
| WEAVE_ERROR err; |
| wifi_mode_t curWiFiMode, targetWiFiMode; |
| |
| targetWiFiMode = (enabled) ? WIFI_MODE_APSTA : WIFI_MODE_STA; |
| |
| // Get the current ESP WiFI mode. |
| err = esp_wifi_get_mode(&curWiFiMode); |
| if (err != ESP_OK) |
| { |
| WeaveLogError(DeviceLayer, "esp_wifi_get_mode() failed: %s", nl::ErrorStr(err)); |
| } |
| SuccessOrExit(err); |
| |
| // If station mode is not already enabled (implying the current mode is WIFI_MODE_AP), change |
| // the mode to WIFI_MODE_APSTA. |
| if (true /* curWiFiMode != targetWiFiMode */) |
| { |
| WeaveLogProgress(DeviceLayer, "Changing ESP WiFi mode: %s -> %s", WiFiModeToStr(curWiFiMode), WiFiModeToStr(targetWiFiMode)); |
| |
| err = esp_wifi_set_mode(targetWiFiMode); |
| if (err != ESP_OK) |
| { |
| WeaveLogError(DeviceLayer, "esp_wifi_set_mode() failed: %s", nl::ErrorStr(err)); |
| } |
| SuccessOrExit(err); |
| } |
| |
| exit: |
| return err; |
| } |
| |
| WiFiSecurityType ESP32Utils::WiFiAuthModeToWeaveWiFiSecurityType(wifi_auth_mode_t authMode) |
| { |
| switch (authMode) |
| { |
| case WIFI_AUTH_OPEN: |
| return kWiFiSecurityType_None; |
| case WIFI_AUTH_WEP: |
| return kWiFiSecurityType_WEP; |
| case WIFI_AUTH_WPA_PSK: |
| return kWiFiSecurityType_WPAPersonal; |
| case WIFI_AUTH_WPA2_PSK: |
| return kWiFiSecurityType_WPA2Personal; |
| case WIFI_AUTH_WPA_WPA2_PSK: |
| return kWiFiSecurityType_WPA2MixedPersonal; |
| case WIFI_AUTH_WPA2_ENTERPRISE: |
| return kWiFiSecurityType_WPA2Enterprise; |
| default: |
| return kWiFiSecurityType_NotSpecified; |
| } |
| } |
| |
| int ESP32Utils::OrderScanResultsByRSSI(const void * _res1, const void * _res2) |
| { |
| const wifi_ap_record_t * res1 = (const wifi_ap_record_t *) _res1; |
| const wifi_ap_record_t * res2 = (const wifi_ap_record_t *) _res2; |
| |
| if (res1->rssi > res2->rssi) |
| { |
| return -1; |
| } |
| if (res1->rssi < res2->rssi) |
| { |
| return 1; |
| } |
| return 0; |
| } |
| |
| const char * ESP32Utils::WiFiModeToStr(wifi_mode_t wifiMode) |
| { |
| switch (wifiMode) |
| { |
| case WIFI_MODE_NULL: |
| return "NULL"; |
| case WIFI_MODE_STA: |
| return "STA"; |
| case WIFI_MODE_AP: |
| return "AP"; |
| case WIFI_MODE_APSTA: |
| return "STA+AP"; |
| default: |
| return "(unknown)"; |
| } |
| } |
| |
| struct netif * ESP32Utils::GetStationNetif(void) |
| { |
| return GetNetif(TCPIP_ADAPTER_IF_STA); |
| } |
| |
| struct netif * ESP32Utils::GetNetif(tcpip_adapter_if_t intfId) |
| { |
| struct netif * netif; |
| return (tcpip_adapter_get_netif(intfId, (void **)&netif) == ESP_OK) ? netif : NULL; |
| } |
| |
| bool ESP32Utils::IsInterfaceUp(tcpip_adapter_if_t intfId) |
| { |
| struct netif * netif = GetNetif(intfId); |
| return netif != NULL && netif_is_up(netif); |
| } |
| |
| const char * ESP32Utils::InterfaceIdToName(tcpip_adapter_if_t intfId) |
| { |
| switch (intfId) |
| { |
| case TCPIP_ADAPTER_IF_STA: |
| return "WiFi station"; |
| case TCPIP_ADAPTER_IF_AP: |
| return "WiFi AP"; |
| case TCPIP_ADAPTER_IF_ETH: |
| return "Ethernet"; |
| default: |
| return "(unknown)"; |
| } |
| } |
| |
| bool ESP32Utils::HasIPv6LinkLocalAddress(tcpip_adapter_if_t intfId) |
| { |
| ip6_addr_t unused; |
| return tcpip_adapter_get_ip6_linklocal(intfId, &unused) == ESP_OK; |
| } |