Files
nuki_hub/src/networkDevices/WifiDevice.cpp
2025-06-09 22:42:30 +02:00

352 lines
9.2 KiB
C++

#include "WifiDevice.h"
#include "../PreferencesKeys.h"
#include "../Logger.h"
#include "../RestartReason.h"
#include "../EspMillis.h"
WifiDevice::WifiDevice(const String& hostname, Preferences* preferences, const IPConfiguration* ipConfiguration)
: NetworkDevice(hostname, preferences, ipConfiguration),
_preferences(preferences)
{
#ifndef NUKI_HUB_UPDATER
NetworkDevice::init();
#endif
}
const String WifiDevice::deviceName() const
{
return "Built-in Wi-Fi";
}
void WifiDevice::initialize()
{
if (_hostname != "fakep4forhosted") {
ssid = _preferences->getString(preference_wifi_ssid, "");
ssid.trim();
pass = _preferences->getString(preference_wifi_pass, "");
pass.trim();
WiFi.setHostname(_hostname.c_str());
WiFi.onEvent([&](WiFiEvent_t event, WiFiEventInfo_t info)
{
onWifiEvent(event, info);
});
if(isWifiConfigured())
{
Log->println(String("Attempting to connect to saved SSID ") + String(ssid));
_openAP = false;
}
else
{
Log->println("No SSID or Wifi password saved, opening AP");
_openAP = true;
}
scan(false, true);
}
else
{
WiFi.disconnect(true);
WiFi.mode(WIFI_STA);
WiFi.disconnect();
delay(5000);
Log->println("Dummy WiFi device for Hosted on P4 done");
}
return;
}
void WifiDevice::scan(bool passive, bool async)
{
if (!_openAP)
{
WiFi.disconnect(true);
WiFi.mode(WIFI_STA);
WiFi.disconnect();
}
WiFi.scanDelete();
WiFi.setScanMethod(WIFI_ALL_CHANNEL_SCAN);
WiFi.setSortMethod(WIFI_CONNECT_AP_BY_SIGNAL);
if(async)
{
Log->println("Wi-Fi async scan started");
}
else
{
Log->println("Wi-Fi sync scan started");
}
if(passive)
{
WiFi.scanNetworks(async,false,true,75U);
}
else
{
WiFi.scanNetworks(async);
}
}
void WifiDevice::openAP()
{
if(_startAP)
{
Log->println("Starting AP with SSID NukiHub and Password NukiHubESP32");
_startAP = false;
WiFi.mode(WIFI_AP);
delay(500);
WiFi.softAPsetHostname(_hostname.c_str());
delay(500);
WiFi.softAP("NukiHub", "NukiHubESP32");
//if(MDNS.begin(_hostname.c_str())){
// MDNS.addService("http", "tcp", 80);
//}
}
}
bool WifiDevice::connect()
{
WiFi.mode(WIFI_STA);
WiFi.setHostname(_hostname.c_str());
delay(500);
int bestConnection = -1;
if(_preferences->getBool(preference_find_best_rssi, false))
{
for (int i = 0; i < _foundNetworks; i++)
{
if (ssid == WiFi.SSID(i))
{
Log->println(String("Saved SSID ") + ssid + String(" found with RSSI: ") +
String(WiFi.RSSI(i)) + String(("(")) +
String(constrain((100.0 + WiFi.RSSI(i)) * 2, 0, 100)) +
String(" %) and BSSID: ") + WiFi.BSSIDstr(i) +
String(" and channel: ") + String(WiFi.channel(i)));
if (bestConnection == -1)
{
bestConnection = i;
}
else
{
if (WiFi.RSSI(i) > WiFi.RSSI(bestConnection))
{
bestConnection = i;
}
}
}
}
if (bestConnection == -1)
{
Log->print("No network found with SSID: ");
Log->println(ssid);
}
else
{
Log->println(String("Trying to connect to SSID ") + ssid + String(" found with RSSI: ") +
String(WiFi.RSSI(bestConnection)) + String(("(")) +
String(constrain((100.0 + WiFi.RSSI(bestConnection)) * 2, 0, 100)) +
String(" %) and BSSID: ") + WiFi.BSSIDstr(bestConnection) +
String(" and channel: ") + String(WiFi.channel(bestConnection)));
}
}
if(!_ipConfiguration->dhcpEnabled())
{
WiFi.config(_ipConfiguration->ipAddress(), _ipConfiguration->dnsServer(), _ipConfiguration->defaultGateway(), _ipConfiguration->subnet());
}
WiFi.begin(ssid, pass);
Log->print("WiFi connecting");
int loop = 0;
while(!isConnected() && loop < 150)
{
Log->print(".");
delay(100);
loop++;
}
Log->println("");
if (!isConnected())
{
Log->println("Failed to connect within 15 seconds");
if(_preferences->getBool(preference_restart_on_disconnect, false) && (espMillis() > 60000))
{
Log->println("Restart on disconnect watchdog triggered, rebooting");
delay(100);
restartEsp(RestartReason::RestartOnDisconnectWatchdog);
}
else
{
Log->println("Retrying WiFi connection");
scan(false, true);
}
return false;
}
return true;
}
bool WifiDevice::isWifiConfigured() const
{
return ssid.length() > 0 && pass.length() > 0;
}
void WifiDevice::reconfigure()
{
_preferences->putString(preference_wifi_ssid, "");
_preferences->putString(preference_wifi_pass, "");
delay(200);
restartEsp(RestartReason::ReconfigureWifi);
}
bool WifiDevice::isConnected()
{
return WiFi.isConnected();
}
void WifiDevice::onConnected()
{
Log->println("Wi-Fi connected");
_connected = true;
}
void WifiDevice::onDisconnected()
{
if (!_connected)
{
return;
}
_connected = false;
Log->println("Wi-Fi disconnected");
connect();
}
int8_t WifiDevice::signalStrength()
{
return WiFi.RSSI();
}
String WifiDevice::localIP()
{
return WiFi.localIP().toString();
}
String WifiDevice::BSSIDstr()
{
return WiFi.BSSIDstr();
}
bool WifiDevice::isApOpen()
{
return _openAP;
}
void WifiDevice::onWifiEvent(const WiFiEvent_t &event, const WiFiEventInfo_t &info)
{
Log->printf("[WiFi-event] event: %d\n", event);
switch (event) {
case ARDUINO_EVENT_WIFI_READY:
Log->println("WiFi interface ready");
break;
case ARDUINO_EVENT_WIFI_SCAN_DONE:
Log->println("Completed scan for access points");
_foundNetworks = WiFi.scanComplete();
for (int i = 0; i < _foundNetworks; i++)
{
Log->println(String("SSID ") + WiFi.SSID(i) + String(" found with RSSI: ") +
String(WiFi.RSSI(i)) + String(("(")) +
String(constrain((100.0 + WiFi.RSSI(i)) * 2, 0, 100)) +
String(" %) and BSSID: ") + WiFi.BSSIDstr(i) +
String(" and channel: ") + String(WiFi.channel(i)));
}
if (_openAP)
{
openAP();
}
else if (_foundNetworks > 0 || _preferences->getBool(preference_find_best_rssi, false))
{
esp_wifi_scan_stop();
connect();
}
else
{
Log->println("No networks found, restarting scan");
scan(false, true);
}
break;
case ARDUINO_EVENT_WIFI_STA_START:
Log->println("WiFi client started");
break;
case ARDUINO_EVENT_WIFI_STA_STOP:
Log->println("WiFi clients stopped");
if(!_openAP)
{
onDisconnected();
}
break;
case ARDUINO_EVENT_WIFI_STA_CONNECTED:
Log->println("Connected to access point");
break;
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
Log->println("Disconnected from WiFi access point");
if(!_openAP)
{
onDisconnected();
}
break;
case ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE:
Log->println("Authentication mode of access point has changed");
break;
case ARDUINO_EVENT_WIFI_STA_GOT_IP:
Log->print("Obtained IP address: ");
Log->println(WiFi.localIP());
if(!_openAP)
{
onConnected();
}
break;
case ARDUINO_EVENT_WIFI_STA_LOST_IP:
Log->println("Lost IP address and IP address is reset to 0");
if(!_openAP)
{
onDisconnected();
}
break;
case ARDUINO_EVENT_WIFI_AP_START:
Log->println("WiFi access point started");
break;
case ARDUINO_EVENT_WIFI_AP_STOP:
Log->println("WiFi access point stopped");
break;
case ARDUINO_EVENT_WIFI_AP_STACONNECTED:
Log->println("Client connected");
break;
case ARDUINO_EVENT_WIFI_AP_STADISCONNECTED:
Log->println("Client disconnected");
break;
case ARDUINO_EVENT_WIFI_AP_STAIPASSIGNED:
Log->println("Assigned IP address to client");
break;
case ARDUINO_EVENT_WIFI_AP_PROBEREQRECVED:
Log->println("Received probe request");
break;
case ARDUINO_EVENT_WIFI_AP_GOT_IP6:
Log->println("AP IPv6 is preferred");
break;
case ARDUINO_EVENT_WIFI_STA_GOT_IP6:
Log->println("STA IPv6 is preferred");
break;
default:
break;
}
}