Preperations for static ip per sta config

This commit is contained in:
2021-08-01 17:28:37 +02:00
parent 01189ca833
commit 07ad3383eb
4 changed files with 356 additions and 221 deletions

View File

@@ -47,9 +47,9 @@ std::optional<espchrono::millis_clock::time_point> _lastStaSwitchedToConnected;
std::optional<espchrono::millis_clock::time_point> lastScanStarted;
espchrono::millis_clock::time_point _lastConnect;
ip_setting lastStaIpSetting;
wifi_entry lastApSetting;
std::optional<static_ip_config> last_sta_static_ip;
static_dns_config last_sta_static_dns;
ap_config last_ap_config;
std::string lastWifisChecksum;
@@ -231,149 +231,119 @@ int goe_wifi_wait_status_bits(int bits, espcpputils::ticks timeout)
timeout.count()) & bits; // Wait a maximum of 100ms for either bit to be set.
}
esp_err_t goe_wifi_set_esp_interface_ip(esp_interface_t interface, ip_address_t local_ip, ip_address_t gateway, ip_address_t subnet)
esp_err_t goe_wifi_set_esp_interface_ip(esp_interface_t interface, const std::optional<static_ip_config> &ip)
{
esp_netif_t *esp_netif = esp_netifs[interface];
esp_netif_dhcp_status_t status = ESP_NETIF_DHCP_INIT;
using wifi_stack::toString;
esp_netif_ip_info_t info;
info.ip.addr = local_ip.value();
info.gw.addr = gateway.value();
info.netmask.addr = subnet.value();
if (ip)
ESP_LOGI(TAG, "%s set STATIC ip=%s subnet=%s gateway=%s", toString(interface).c_str(),
toString(ip->ip).c_str(), toString(ip->subnet).c_str(), toString(ip->gateway).c_str());
else
ESP_LOGI(TAG, "%s set DYNAMIC", toString(interface).c_str());
if (true)
if (interface == ESP_IF_WIFI_AP)
{
ESP_LOGI(TAG, "Configuring %s static IP: " IPSTR ", MASK: " IPSTR ", GW: " IPSTR,
interface == ESP_IF_WIFI_STA ? "Station" :
interface == ESP_IF_WIFI_AP ? "SoftAP" : "Ethernet",
IP2STR(&info.ip), IP2STR(&info.netmask), IP2STR(&info.gw));
ESP_LOGE(TAG, "setting IP for AP must be done with goe_wifi_set_ap_ip() instead!");
return ESP_FAIL;
}
if (interface != ESP_IF_WIFI_AP)
esp_netif_t *esp_netif = esp_netifs[interface];
{
esp_netif_dhcp_status_t status = ESP_NETIF_DHCP_INIT;
if (const auto result = esp_netif_dhcpc_get_status(esp_netif, &status); result != ESP_OK)
{
ESP_LOGE(TAG, "esp_netif_dhcpc_get_status() failed with %s", esp_err_to_name(result));
return result;
}
if (const auto result = esp_netif_dhcpc_stop(esp_netif); result != ESP_OK && result != ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED)
{
ESP_LOGE(TAG, "esp_netif_dhcpc_stop() failed with %s", esp_err_to_name(result));
return result;
}
}
if (const auto result = esp_netif_dhcpc_stop(esp_netif); !cpputils::is_in(result, ESP_OK, ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED))
{
ESP_LOGE(TAG, "esp_netif_dhcpc_stop() failed with %s", esp_err_to_name(result));
return result;
}
{
esp_netif_ip_info_t info;
info.ip.addr = ip ? ip->ip.value() : 0;
info.netmask.addr = ip ? ip->subnet.value() : 0;
info.gw.addr = ip ? ip->gateway.value() : 0;
if (const auto result = esp_netif_set_ip_info(esp_netif, &info); result != ESP_OK)
{
ESP_LOGE(TAG, "esp_netif_set_ip_info() failed with %s", esp_err_to_name(result));
return result;
}
if (info.ip.addr == 0)
{
ESP_LOGI(TAG, "starting dhcpc");
if (const auto result = esp_netif_dhcpc_start(esp_netif); result != ESP_OK)
{
ESP_LOGE(TAG, "esp_netif_dhcpc_start() failed with %s", esp_err_to_name(result));
return result;
}
#if LWIP_IPV6 && LWIP_IPV6_DHCP6_STATELESS
if (const auto result = dhcp6_enable_stateless(esp_netif_get_netif_impl(esp_netif)); result != ESP_OK)
{
ESP_LOGE(TAG, "dhcp6_enable_stateless() failed with %s", esp_err_to_name(result));
return result;
}
#endif
}
}
else
if (!ip)
{
if (const auto result = esp_netif_dhcps_get_status(esp_netif, &status); result != ESP_OK)
ESP_LOGI(TAG, "starting dhcpc");
if (const auto result = esp_netif_dhcpc_start(esp_netif); result != ESP_OK)
{
ESP_LOGE(TAG, "esp_netif_dhcps_get_status() failed with %s", esp_err_to_name(result));
ESP_LOGE(TAG, "esp_netif_dhcpc_start() failed with %s", esp_err_to_name(result));
return result;
}
for (int i = 0; ; i++)
#if LWIP_IPV6 && LWIP_IPV6_DHCP6_STATELESS
if (const auto result = dhcp6_enable_stateless(esp_netif_get_netif_impl(esp_netif)); result != ESP_OK)
{
if (const auto result = esp_netif_dhcps_stop(esp_netif); result != ESP_OK)
{
ESP_LOGE(TAG, "esp_netif_dhcps_stop() failed with %s", esp_err_to_name(result));
if (result != ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED)
return result;
}
if (const auto result = esp_netif_set_ip_info(esp_netif, &info); result == ESP_OK)
break;
else
{
ESP_LOGE(TAG, "esp_netif_set_ip_info() for AP failed with %s", esp_err_to_name(result));
if (result == ESP_ERR_ESP_NETIF_DHCP_NOT_STOPPED)
{
if (i < 20)
{
vTaskDelay(std::chrono::ceil<espcpputils::ticks>(50ms).count());
continue;
}
else
ESP_LOGE(TAG, "esp_netif_set_ip_info() giving up after 20 tries");
}
return result;
}
}
dhcps_lease_t lease;
lease.enable = true;
lease.start_ip.addr = local_ip.value() + (1 << 24);
lease.end_ip.addr = local_ip.value() + (11 << 24);
if (const auto result = tcpip_adapter_dhcps_option((tcpip_adapter_dhcp_option_mode_t)TCPIP_ADAPTER_OP_SET, (tcpip_adapter_dhcp_option_id_t)REQUESTED_IP_ADDRESS, (void*)&lease, sizeof(dhcps_lease_t));
result != ESP_OK)
{
ESP_LOGE(TAG, "tcpip_adapter_dhcps_option() failed with %s", esp_err_to_name(result));
return result;
}
if (const auto result = esp_netif_dhcps_start(esp_netif); result != ESP_OK)
{
ESP_LOGE(TAG, "esp_netif_dhcps_start() failed with %s", esp_err_to_name(result));
ESP_LOGE(TAG, "dhcp6_enable_stateless() failed with %s", esp_err_to_name(result));
return result;
}
#endif
}
return ESP_OK;
}
esp_err_t goe_wifi_set_esp_interface_dns(esp_interface_t interface, ip_address_t main_dns, ip_address_t backup_dns, ip_address_t fallback_dns)
esp_err_t goe_wifi_set_esp_interface_dns(esp_interface_t interface, const static_dns_config &dns)
{
esp_netif_t *esp_netif = esp_netifs[interface];
esp_netif_dns_info_t dns;
dns.ip.type = ESP_IPADDR_TYPE_V4;
if ((dns.ip.u_addr.ip4.addr = main_dns.value()))
esp_netif_dns_info_t dns_info;
dns_info.ip.type = ESP_IPADDR_TYPE_V4;
if (dns.main)
{
if (const auto result = esp_netif_set_dns_info(esp_netif, ESP_NETIF_DNS_MAIN, &dns); result != ESP_OK)
dns_info.ip.u_addr.ip4.addr = dns.main->value();
if (const auto result = esp_netif_set_dns_info(esp_netif, ESP_NETIF_DNS_MAIN, &dns_info); result != ESP_OK)
{
ESP_LOGE(TAG, "esp_netif_set_dns_info() for MAIN failed with %s", esp_err_to_name(result));
return result;
}
}
if (interface != ESP_IF_WIFI_AP)
if (dns.backup)
{
if ((dns.ip.u_addr.ip4.addr = backup_dns.value()))
if (interface != ESP_IF_WIFI_AP)
{
if (const auto result = esp_netif_set_dns_info(esp_netif, ESP_NETIF_DNS_BACKUP, &dns); result != ESP_OK)
dns_info.ip.u_addr.ip4.addr = dns.backup->value();
if (const auto result = esp_netif_set_dns_info(esp_netif, ESP_NETIF_DNS_BACKUP, &dns_info); result != ESP_OK)
{
ESP_LOGE(TAG, "esp_netif_set_dns_info() for BACKUP failed with %s", esp_err_to_name(result));
return result;
}
}
else
ESP_LOGE(TAG, "setting static backup DNS for AP is not allowed!");
}
if ((dns.ip.u_addr.ip4.addr = fallback_dns.value()))
if (dns.fallback)
{
if (interface != ESP_IF_WIFI_AP)
{
if (const auto result = esp_netif_set_dns_info(esp_netif, ESP_NETIF_DNS_FALLBACK, &dns); result != ESP_OK)
dns_info.ip.u_addr.ip4.addr = dns.fallback->value();
if (const auto result = esp_netif_set_dns_info(esp_netif, ESP_NETIF_DNS_FALLBACK, &dns_info); result != ESP_OK)
{
ESP_LOGE(TAG, "esp_netif_set_dns_info() for FALLBACK failed with %s", esp_err_to_name(result));
return result;
}
}
else
ESP_LOGE(TAG, "setting static fallback DNS for AP is not allowed!");
}
return ESP_OK;
@@ -422,62 +392,54 @@ esp_err_t goe_wifi_enable_ap(bool enable, const config &config)
return result;
}
void goe_wifi_softap_config(wifi_config_t &wifi_config, const std::string &ssid={}, const std::string &password={},
uint8_t channel = 1, wifi_auth_mode_t authmode = WIFI_AUTH_WPA_WPA2_PSK,
bool ssid_hidden = false, uint8_t max_connections = 4, uint16_t beacon_interval = 100)
wifi_config_t make_ap_config(const ap_config &ap_config)
{
wifi_config.ap.channel = channel;
wifi_config.ap.max_connection = max_connections;
wifi_config.ap.beacon_interval = beacon_interval;
wifi_config.ap.ssid_hidden = ssid_hidden;
wifi_config_t wifi_config;
wifi_config.ap.channel = ap_config.channel;
wifi_config.ap.max_connection = ap_config.max_connection;
wifi_config.ap.beacon_interval = ap_config.beacon_interval;
wifi_config.ap.ssid_hidden = false;
wifi_config.ap.authmode = WIFI_AUTH_OPEN;
wifi_config.ap.ssid_len = 0;
wifi_config.ap.ssid[0] = 0;
wifi_config.ap.password[0] = 0;
if (!ssid.empty())
if (!ap_config.ssid.empty())
{
std::snprintf((char*)wifi_config.ap.ssid, sizeof(wifi_config.ap.ssid), "%s", ssid.c_str());
wifi_config.ap.ssid_len = ssid.size();
if (!password.empty())
std::snprintf((char*)wifi_config.ap.ssid, sizeof(wifi_config.ap.ssid), "%s", ap_config.ssid.c_str());
wifi_config.ap.ssid_len = ap_config.ssid.size();
if (!ap_config.key.empty())
{
wifi_config.ap.authmode = authmode;
std::snprintf((char*)wifi_config.ap.password, sizeof(wifi_config.ap.password), "%s", password.c_str());
wifi_config.ap.authmode = ap_config.authmode;
std::snprintf((char*)wifi_config.ap.password, sizeof(wifi_config.ap.password), "%s", ap_config.key.c_str());
}
}
return wifi_config;
}
esp_err_t goe_wifi_set_ap_config(const config &config, const std::string &ssid, const std::string &passphrase={},
int channel = 1, wifi_auth_mode_t authmode = WIFI_AUTH_WPA_WPA2_PSK,
bool ssid_hidden = false, int max_connection = 4, uint16_t beacon_interval = 100)
esp_err_t goe_wifi_set_ap_config(const config &config, const ap_config &ap_config)
{
if (const auto result = goe_wifi_enable_ap(true, config); result != ESP_OK)
{
ESP_LOGE(TAG, "goe_wifi_enable_ap() failed with %s", esp_err_to_name(result));
return result;
}
if (ssid.empty())
if (ap_config.ssid.empty())
{
ESP_LOGE(TAG, "SSID missing!");
return ESP_FAIL;
}
if (!passphrase.empty())
if (!ap_config.key.empty())
{
if (passphrase.size() < 8)
if (ap_config.key.size() < 8)
{
ESP_LOGE(TAG, "passphrase too short! (size=%zd)", passphrase.size());
ESP_LOGE(TAG, "passphrase too short! (size=%zd)", ap_config.key.size());
return ESP_FAIL;
}
if (passphrase.size() > 63)
if (ap_config.key.size() > 63)
{
ESP_LOGE(TAG, "passphrase too long! (size=%zd)", passphrase.size());
ESP_LOGE(TAG, "passphrase too long! (size=%zd)", ap_config.key.size());
return ESP_FAIL;
}
}
wifi_config_t conf;
goe_wifi_softap_config(conf, ssid, passphrase, channel, authmode, ssid_hidden, max_connection);
wifi_config_t conf = make_ap_config(ap_config);
wifi_config_t conf_current;
if (const auto result = esp_wifi_get_config(WIFI_IF_AP, &conf_current); result != ESP_OK)
@@ -1238,31 +1200,89 @@ esp_err_t goe_wifi_set_mode(wifi_mode_t m, const config &config)
return ESP_OK;
}
esp_err_t goe_wifi_set_ap_ip(const config &config, ip_address_t local_ip, ip_address_t gateway, ip_address_t subnet)
esp_err_t goe_wifi_set_ap_ip(const config &config, const static_ip_config &ip)
{
if (const auto result = goe_wifi_enable_ap(true, config); result != ESP_OK)
ESP_LOGI(TAG, "ip=%s subnet=%s gateway=%s", toString(ip.ip).c_str(), toString(ip.subnet).c_str(), toString(ip.gateway).c_str());
esp_netif_t *esp_netif = esp_netifs[ESP_IF_WIFI_AP];
esp_netif_dhcp_status_t status = ESP_NETIF_DHCP_INIT;
if (const auto result = esp_netif_dhcps_get_status(esp_netif, &status); result != ESP_OK)
{
ESP_LOGE(TAG, "goe_wifi_enable_ap() failed with %s", esp_err_to_name(result));
ESP_LOGE(TAG, "esp_netif_dhcps_get_status() failed with %s", esp_err_to_name(result));
return result;
}
if (const auto result = goe_wifi_set_esp_interface_ip(ESP_IF_WIFI_AP, local_ip, gateway, subnet); result != ESP_OK)
for (int i = 0; ; i++)
{
ESP_LOGE(TAG, "goe_wifi_set_esp_interface_ip() for AP failed with %s", esp_err_to_name(result));
if (const auto result = esp_netif_dhcps_stop(esp_netif); result != ESP_OK)
{
ESP_LOGE(TAG, "esp_netif_dhcps_stop() failed with %s", esp_err_to_name(result));
if (result != ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED)
return result;
}
esp_netif_ip_info_t info;
info.ip.addr = ip.ip.value();
info.netmask.addr = ip.subnet.value();
info.gw.addr = ip.gateway.value();
if (const auto result = esp_netif_set_ip_info(esp_netif, &info); result == ESP_OK)
break;
else
{
ESP_LOGE(TAG, "esp_netif_set_ip_info() for AP failed with %s", esp_err_to_name(result));
if (result == ESP_ERR_ESP_NETIF_DHCP_NOT_STOPPED)
{
if (i < 20)
{
vTaskDelay(std::chrono::ceil<espcpputils::ticks>(50ms).count());
continue;
}
else
ESP_LOGE(TAG, "esp_netif_set_ip_info() giving up after 20 tries");
}
return result;
}
}
{
dhcps_lease_t lease;
lease.enable = true;
lease.start_ip.addr = ip.ip.value() + (1 << 24);
lease.end_ip.addr = ip.ip.value() + (11 << 24);
if (const auto result = tcpip_adapter_dhcps_option(
(tcpip_adapter_dhcp_option_mode_t)TCPIP_ADAPTER_OP_SET,
(tcpip_adapter_dhcp_option_id_t)REQUESTED_IP_ADDRESS,
(void*)&lease,
sizeof(dhcps_lease_t)
); result != ESP_OK)
{
ESP_LOGE(TAG, "tcpip_adapter_dhcps_option() failed with %s", esp_err_to_name(result));
return result;
}
}
if (const auto result = esp_netif_dhcps_start(esp_netif); result != ESP_OK)
{
ESP_LOGE(TAG, "esp_netif_dhcps_start() failed with %s", esp_err_to_name(result));
return result;
}
return ESP_OK;
}
void goe_wifi_sta_config(const config &config, wifi_config_t &wifi_config, const std::string &ssid={}, const std::string &password={},
std::optional<mac_t> bssid={}, uint8_t channel=0)
wifi_config_t make_sta_config(std::string_view ssid, std::string_view password, int8_t min_rssi,
std::optional<mac_t> bssid, uint8_t channel)
{
wifi_config_t wifi_config;
wifi_config.sta.channel = channel;
wifi_config.sta.listen_interval = 0;
wifi_config.sta.scan_method = WIFI_FAST_SCAN; //WIFI_ALL_CHANNEL_SCAN or WIFI_FAST_SCAN
wifi_config.sta.sort_method = WIFI_CONNECT_AP_BY_SIGNAL; //WIFI_CONNECT_AP_BY_SIGNAL or WIFI_CONNECT_AP_BY_SECURITY
wifi_config.sta.threshold.rssi = config.min_rssi;
wifi_config.sta.threshold.rssi = min_rssi;
wifi_config.sta.pmf_cfg.capable = true;
wifi_config.sta.pmf_cfg.required = false;
wifi_config.sta.bssid_set = 0;
@@ -1273,12 +1293,12 @@ void goe_wifi_sta_config(const config &config, wifi_config_t &wifi_config, const
if (!ssid.empty())
{
std::snprintf((char*)wifi_config.sta.ssid, sizeof(wifi_config.sta.ssid), "%s", ssid.c_str());
std::snprintf((char*)wifi_config.sta.ssid, sizeof(wifi_config.sta.ssid), "%s", ssid.data());
if (!password.empty())
{
wifi_config.sta.threshold.authmode = WIFI_AUTH_WEP;
std::snprintf((char*)wifi_config.sta.password, sizeof(wifi_config.sta.password), "%s", password.c_str());
std::snprintf((char*)wifi_config.sta.password, sizeof(wifi_config.sta.password), "%s", password.data());
}
if (bssid)
@@ -1287,12 +1307,12 @@ void goe_wifi_sta_config(const config &config, wifi_config_t &wifi_config, const
bssid->copyTo(wifi_config.sta.bssid);
}
}
return wifi_config;
}
esp_err_t applyStaConfig(const config &config);
esp_err_t goe_wifi_sta_begin(const config &config, const std::string &ssid, const std::string &passphrase, int32_t channel,
std::optional<mac_t> bssid, bool connect)
std::optional<mac_t> bssid, bool connect)
{
if (const auto result = goe_wifi_enable_sta(true, config); result != ESP_OK)
{
@@ -1327,8 +1347,7 @@ esp_err_t goe_wifi_sta_begin(const config &config, const std::string &ssid, cons
}
}
wifi_config_t conf;
goe_wifi_sta_config(config, conf, ssid, passphrase, bssid, channel);
wifi_config_t conf = make_sta_config(ssid, passphrase, config.sta.min_rssi, bssid, channel);
wifi_config_t current_conf;
if (const auto result = esp_wifi_get_config(WIFI_IF_STA, &current_conf); result != ESP_OK)
@@ -1365,12 +1384,22 @@ esp_err_t goe_wifi_sta_begin(const config &config, const std::string &ssid, cons
}
}
if (const auto result = applyStaConfig(config); result != ESP_OK)
if (const auto result = goe_wifi_set_esp_interface_ip(ESP_IF_WIFI_STA, config.sta.static_ip); result != ESP_OK)
{
ESP_LOGE(TAG, "applyStaConfig() failed with %s", esp_err_to_name(result));
ESP_LOGE(TAG, "goe_wifi_set_esp_interface_ip() for STA failed with %s", esp_err_to_name(result));
return result;
}
last_sta_static_ip = config.sta.static_ip;
if (const auto result = goe_wifi_set_esp_interface_dns(ESP_IF_WIFI_STA, config.sta.static_dns); result != ESP_OK)
{
ESP_LOGE(TAG, "goe_wifi_set_esp_interface_dns() for STA failed with %s", esp_err_to_name(result));
return result;
}
last_sta_static_dns = config.sta.static_dns;
if (connect)
{
_wifiConnectFailFlag = std::nullopt;
@@ -1408,12 +1437,22 @@ esp_err_t goe_wifi_sta_begin(const config &config)
return result;
}
if (const auto result = applyStaConfig(config); result != ESP_OK)
if (const auto result = goe_wifi_set_esp_interface_ip(ESP_IF_WIFI_STA, config.sta.static_ip); result != ESP_OK)
{
ESP_LOGE(TAG, "applyStaConfig() failed with %s", esp_err_to_name(result));
ESP_LOGE(TAG, "goe_wifi_set_esp_interface_ip() for STA failed with %s", esp_err_to_name(result));
return result;
}
last_sta_static_ip = config.sta.static_ip;
if (const auto result = goe_wifi_set_esp_interface_dns(ESP_IF_WIFI_STA, config.sta.static_dns); result != ESP_OK)
{
ESP_LOGE(TAG, "goe_wifi_set_esp_interface_dns() for STA failed with %s", esp_err_to_name(result));
return result;
}
last_sta_static_dns = config.sta.static_dns;
if (get_sta_status() != WiFiStaStatus::WL_CONNECTED)
{
_wifiConnectFailFlag = std::nullopt;
@@ -1436,8 +1475,7 @@ esp_err_t goe_wifi_sta_disconnect(const config &config, bool wifioff, bool erase
{
ESP_LOGI(TAG, "wifioff=%s eraseap=%s", wifioff?"true":"false", eraseap?"true":"false");
wifi_config_t conf;
goe_wifi_sta_config(config, conf);
wifi_config_t conf = make_sta_config({}, {}, 0, {}, 0);
if (!(goe_wifi_get_mode() & WIFI_MODE_STA))
return ESP_FAIL;
@@ -1471,33 +1509,10 @@ esp_err_t goe_wifi_sta_disconnect(const config &config, bool wifioff, bool erase
return ESP_OK;
}
esp_err_t applyStaConfig(const config &config)
{
lastStaIpSetting = config.sta_ip;
if (const auto result = config.sta_ip.staticIpEnabled ?
goe_wifi_set_esp_interface_ip(ESP_IF_WIFI_STA, config.sta_ip.staticIp, config.sta_ip.staticGateway, config.sta_ip.staticSubnet) :
goe_wifi_set_esp_interface_ip(ESP_IF_WIFI_STA, {}, {}, {}); result != ESP_OK)
{
ESP_LOGE(TAG, "goe_wifi_set_esp_interface_ip() for STA failed with %s", esp_err_to_name(result));
return result;
}
if (const auto result = config.sta_ip.staticIpEnabled ?
goe_wifi_set_esp_interface_dns(ESP_IF_WIFI_STA, config.sta_ip.staticDns1, config.sta_ip.staticDns2, {}) :
goe_wifi_set_esp_interface_dns(ESP_IF_WIFI_STA, {}, {}, {}); result != ESP_OK)
{
ESP_LOGE(TAG, "goe_wifi_set_esp_interface_dns() for STA failed with %s", esp_err_to_name(result));
return result;
}
return ESP_OK;
}
std::string calculateWifisChecksum(const config &config)
{
std::string result;
for (const auto &wifi : config.wifis)
for (const auto &wifi : config.sta.wifis)
{
result += wifi.ssid;
result += ",";
@@ -1594,9 +1609,9 @@ bool buildConnectPlan(const config &config, const scan_result &scanResult)
if (std::any_of(std::begin(connectPlan), std::end(connectPlan), [&scanSSID](const auto &entry){ return cpputils::stringEqualsIgnoreCase(entry.ssid, scanSSID); }))
continue;
const auto iter = std::find_if(std::begin(config.wifis), std::end(config.wifis),
const auto iter = std::find_if(std::begin(config.sta.wifis), std::end(config.sta.wifis),
[&scanSSID](const auto &entry){ return cpputils::stringEqualsIgnoreCase(entry.ssid, scanSSID); });
if (iter != std::end(config.wifis))
if (iter != std::end(config.sta.wifis))
{
connectPlan.emplace_back(ConnectPlanItem{
.ssid = std::string{scanSSID},
@@ -1628,8 +1643,23 @@ bool buildConnectPlan(const config &config, const scan_result &scanResult)
toString(entry.bssid).c_str()
);
_lastConnect = espchrono::millis_clock::now();
//if (const auto result = applyStaConfig(config); result != ESP_OK)
// ESP_LOGE(TAG, "applyStaConfig() failed with %s", esp_err_to_name(result));
// if (const auto result = goe_wifi_set_esp_interface_ip(ESP_IF_WIFI_STA, config.sta.static_ip); result != ESP_OK)
// {
// ESP_LOGE(TAG, "goe_wifi_set_esp_interface_ip() for STA failed with %s", esp_err_to_name(result));
// return result;
// }
// last_sta_static_ip = config.sta.static_ip;
// if (const auto result = goe_wifi_set_esp_interface_dns(ESP_IF_WIFI_STA, config.sta.static_dns); result != ESP_OK)
// {
// ESP_LOGE(TAG, "goe_wifi_set_esp_interface_dns() for STA failed with %s", esp_err_to_name(result));
// return result;
// }
// last_sta_static_dns = config.sta.static_dns;
_wifiConnectFailCounter = 0;
if (const auto result = goe_wifi_sta_begin(config, entry.ssid, entry.key, entry.channel, entry.bssid); result != ESP_OK)
ESP_LOGE(TAG, "goe_wifi_sta_begin() failed with %s", esp_err_to_name(result));
@@ -1642,7 +1672,7 @@ bool buildConnectPlan(const config &config, const scan_result &scanResult)
ESP_LOGW(TAG, "no configured ssid found");
ESP_LOGW(TAG, "found ssids: %s", foundSsids.c_str());
std::string configuredSsids;
for (const auto &config : config.wifis)
for (const auto &config : config.sta.wifis)
{
if (!configuredSsids.empty())
configuredSsids += ", ";
@@ -1683,17 +1713,30 @@ void init(const config &config)
if (const auto result = goe_wifi_set_mode(WIFI_MODE_APSTA, config); result != ESP_OK)
{
ESP_LOGE(TAG, "goe_wifi_set_mode() failed with %s", esp_err_to_name(result));
return;
}
vTaskDelay(std::chrono::ceil<espcpputils::ticks>(100ms).count());
if (const auto result = goe_wifi_set_ap_ip(config, config.ap.ip, config.ap.ip, config.ap.subnet); result != ESP_OK)
if (const auto result = goe_wifi_enable_ap(true, config); result != ESP_OK)
{
ESP_LOGE(TAG, "goe_wifi_enable_ap() failed with %s", esp_err_to_name(result));
return;
}
if (const auto result = goe_wifi_set_ap_ip(config, config.ap.static_ip); result != ESP_OK)
{
ESP_LOGE(TAG, "goe_wifi_set_ap_ip() failed with %s", esp_err_to_name(result));
return;
}
if (const auto result = goe_wifi_set_ap_config(config, config.ap.ssid, config.ap.key, config.ap.channel, config.ap.authmode, config.ap.ssid_hidden, config.ap.max_connection, config.ap.beacon_interval); result != ESP_OK)
if (const auto result = goe_wifi_set_ap_config(config, config.ap); result != ESP_OK)
{
ESP_LOGE(TAG, "goe_wifi_set_ap_config() failed with %s", esp_err_to_name(result));
return;
}
lastApSetting = config.ap;
last_ap_config = config.ap;
_wifiState = WiFiState::None;
@@ -1711,19 +1754,23 @@ void update(const config &config)
{
handleWifiEvents(config, 0);
if (lastApSetting != config.ap)
if (last_ap_config != config.ap)
{
ESP_LOGI(TAG, "AP settings changed, applying new config...");
ESP_LOGD(TAG, "wifiApName=\"%s\" lastWifiApName=\"%s\"", config.ap.ssid.c_str(), lastApSetting.ssid.c_str());
ESP_LOGD(TAG, "wifiApName=\"%s\" lastWifiApName=\"%s\"", config.ap.key.c_str(), lastApSetting.key.c_str());
if (const auto result = goe_wifi_set_ap_ip(config, config.ap.ip, config.ap.ip, config.ap.subnet); result != ESP_OK)
if (config.ap.ssid != last_ap_config.ssid)
ESP_LOGD(TAG, "new ap ssid=\"%s\" old ap ssid=\"%s\"", config.ap.ssid.c_str(), last_ap_config.ssid.c_str());
if (config.ap.key != last_ap_config.key)
ESP_LOGD(TAG, "new ap key=\"%s\" old ap key=\"%s\"", config.ap.key.c_str(), last_ap_config.key.c_str());
if (const auto result = goe_wifi_set_ap_ip(config, config.ap.static_ip); result != ESP_OK)
ESP_LOGE(TAG, "goe_wifi_set_ap_ip() failed with %s", esp_err_to_name(result));
if (const auto result = goe_wifi_set_ap_config(config, config.ap.ssid, config.ap.key, config.ap.channel, config.ap.authmode, config.ap.ssid_hidden, config.ap.max_connection, config.ap.beacon_interval); result != ESP_OK)
if (const auto result = goe_wifi_set_ap_config(config, config.ap); result != ESP_OK)
ESP_LOGE(TAG, "goe_wifi_set_ap_config() failed with %s", esp_err_to_name(result));
lastApSetting = config.ap;
last_ap_config = config.ap;
}
if (scanResultChangedFlag)
@@ -1744,7 +1791,7 @@ void update(const config &config)
}
else
{
const auto anyWifiConfigured = std::any_of(std::begin(config.wifis), std::end(config.wifis),
const auto anyWifiConfigured = std::any_of(std::begin(config.sta.wifis), std::end(config.sta.wifis),
[](const auto &entry){ return !entry.ssid.empty(); });
if (anyWifiConfigured)
{
@@ -1908,7 +1955,7 @@ void update(const config &config)
else if (const auto sta_info = get_sta_ap_info())
{
const std::string_view connectedSSID{reinterpret_cast<const char *>(sta_info->ssid)};
const auto configStillFound = std::any_of(std::begin(config.wifis), std::end(config.wifis),
const auto configStillFound = std::any_of(std::begin(config.sta.wifis), std::end(config.sta.wifis),
[&connectedSSID](const auto &entry){
return cpputils::stringEqualsIgnoreCase(entry.ssid, connectedSSID);
});
@@ -1923,11 +1970,33 @@ void update(const config &config)
setWifiState(WiFiState::None); // results in another scan
}
else if (lastStaIpSetting != config.sta_ip)
else
{
ESP_LOGI(TAG, "wifi static ip config changed, applying new config");
if (const auto result = applyStaConfig(config); result != ESP_OK)
ESP_LOGE(TAG, "applyStaConfig() failed with %s", esp_err_to_name(result));
if (last_sta_static_ip != config.sta.static_ip)
{
ESP_LOGI(TAG, "wifi static ip config changed, applying new config");
if (const auto result = goe_wifi_set_esp_interface_ip(ESP_IF_WIFI_STA, config.sta.static_ip); result != ESP_OK)
{
ESP_LOGE(TAG, "goe_wifi_set_esp_interface_ip() for STA failed with %s", esp_err_to_name(result));
//return result;
}
else
last_sta_static_ip = config.sta.static_ip;
}
if (last_sta_static_dns != config.sta.static_dns)
{
ESP_LOGI(TAG, "wifi static dns config changed, applying new config");
if (const auto result = goe_wifi_set_esp_interface_dns(ESP_IF_WIFI_STA, config.sta.static_dns); result != ESP_OK)
{
ESP_LOGE(TAG, "goe_wifi_set_esp_interface_dns() for STA failed with %s", esp_err_to_name(result));
//return result;
}
else
last_sta_static_dns = config.sta.static_dns;
}
}
}
else

View File

@@ -4,6 +4,7 @@
#include <string>
#include <array>
#include <cstdint>
#include <optional>
// esp-idf includes
#include <esp_wifi_types.h>
@@ -29,54 +30,89 @@ struct wifi_entry
}
};
struct ap_config : public wifi_entry
struct static_ip_config
{
int channel;
wifi_auth_mode_t authmode;
bool ssid_hidden;
int max_connection;
uint16_t beacon_interval;
ip_address_t ip;
ip_address_t subnet;
ip_address_t gateway;
friend bool operator==(const ap_config &left, const ap_config &right)
friend bool operator==(const static_ip_config &left, const static_ip_config &right)
{
return *static_cast<const wifi_entry *>(&left) == *static_cast<const wifi_entry *>(&right) &&
left.channel == right.channel &&
left.authmode == right.authmode &&
left.ssid_hidden == right.ssid_hidden &&
left.max_connection == right.max_connection &&
left.beacon_interval == right.beacon_interval &&
left.ip == right.ip &&
left.subnet == right.subnet;
return left.ip == right.ip &&
left.subnet == right.subnet &&
left.gateway == right.gateway;
}
friend bool operator!=(const ap_config &left, const ap_config &right)
friend bool operator!=(const static_ip_config &left, const static_ip_config &right)
{
return !(left == right);
}
};
struct ip_setting
struct static_dns_config
{
bool staticIpEnabled;
ip_address_t staticIp;
ip_address_t staticGateway;
ip_address_t staticSubnet;
ip_address_t staticDns1;
ip_address_t staticDns2;
std::optional<ip_address_t> main;
std::optional<ip_address_t> backup;
std::optional<ip_address_t> fallback;
friend bool operator==(const ip_setting &left, const ip_setting &right)
friend bool operator==(const static_dns_config &left, const static_dns_config &right)
{
return left.staticIpEnabled == right.staticIpEnabled &&
left.staticIp == right.staticIp &&
left.staticGateway == right.staticGateway &&
left.staticSubnet == right.staticSubnet &&
left.staticDns1 == right.staticDns1 &&
left.staticDns2 == right.staticDns2;
return left.main == right.main &&
left.backup == right.backup &&
left.fallback == right.fallback;
}
friend bool operator!=(const ip_setting &left, const ip_setting &right)
friend bool operator!=(const static_dns_config &left, const static_dns_config &right)
{
return !(left == right);
}
};
struct sta_config
{
std::array<wifi_entry, 10> wifis;
std::optional<static_ip_config> static_ip;
static_dns_config static_dns;
int8_t min_rssi;
friend bool operator==(const sta_config &left, const sta_config &right)
{
return left.wifis == right.wifis &&
left.static_ip == right.static_ip &&
left.static_dns == right.static_dns &&
left.min_rssi == right.min_rssi;
}
friend bool operator!=(const sta_config &left, const sta_config &right)
{
return !(left == right);
}
};
struct ap_config
{
std::string ssid;
std::string key;
static_ip_config static_ip;
int channel;
wifi_auth_mode_t authmode;
bool ssid_hidden;
int max_connection;
uint16_t beacon_interval;
friend bool operator==(const ap_config &left, const ap_config &right)
{
return left.ssid == right.ssid &&
left.key == right.key &&
left.static_ip == right.static_ip &&
left.channel == right.channel &&
left.authmode == right.authmode &&
left.ssid_hidden == right.ssid_hidden &&
left.max_connection == right.max_connection &&
left.beacon_interval == right.beacon_interval;
}
friend bool operator!=(const ap_config &left, const ap_config &right)
{
return !(left == right);
}
@@ -86,9 +122,20 @@ struct config
{
bool wifiEnabled;
std::string hostname;
std::array<wifi_entry, 10> wifis;
ip_setting sta_ip;
sta_config sta;
ap_config ap;
int8_t min_rssi;
friend bool operator==(const config &left, const config &right)
{
return left.wifiEnabled == right.wifiEnabled &&
left.hostname == right.hostname &&
left.sta == right.sta &&
left.ap == right.ap;
}
friend bool operator!=(const config &left, const config &right)
{
return !(left == right);
}
};
} // namespace wifi_stack

View File

@@ -3,6 +3,9 @@
// esp-idf includes
#include <esp_log.h>
// local includes
#include "futurecpp.h"
namespace wifi_stack {
namespace {
constexpr const char * const TAG = "WIFI_STACK";
@@ -207,4 +210,18 @@ std::string toString(ip_addr_t val)
return "unknown ipv" + std::to_string(val.type);
}
}
std::string toString(esp_interface_t interface)
{
switch (interface)
{
case ESP_IF_WIFI_STA: return "STA";
case ESP_IF_WIFI_AP: return "AP";
case ESP_IF_ETH: return "ETH";
default:
ESP_LOGW(TAG, "unknown esp_interface_t(%i)", std::to_underlying(interface));
return "unknown esp_interface_t(" + std::to_string(std::to_underlying(interface)) + ")";
}
}
} // namespace wifi_stack

View File

@@ -101,4 +101,6 @@ inline std::string toString(const esp_ip4_addr_t &val)
inline std::string toString(const esp_ip6_addr_t &val)
{ return toString(*reinterpret_cast<const ip6_addr_t *>(&val)); }
std::string toString(esp_interface_t interface);
} // namespace wifi_stack