blob: bc5cea6d2dd89946b3e71462934376f17bad3709 [file] [log] [blame]
/*
*
* 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;
}