Files
arduino/src/AgWiFiConnector.cpp

342 lines
8.7 KiB
C++
Raw Normal View History

2024-04-03 11:40:46 +07:00
#include "AgWiFiConnector.h"
#include "Libraries/WiFiManager/WiFiManager.h"
2024-04-03 11:40:46 +07:00
2024-04-03 21:26:04 +07:00
#define WIFI_CONNECT_COUNTDOWN_MAX 180
#define WIFI_HOTSPOT_PASSWORD_DEFAULT "cleanair"
#define WIFI() ((WiFiManager *)(this->wifi))
/**
2024-04-07 16:39:01 +07:00
* @brief Set reference AirGradient instance
*
2024-04-07 16:39:01 +07:00
* @param ag Point to AirGradient instance
*/
2024-04-07 16:39:01 +07:00
void WifiConnector::setAirGradient(AirGradient *ag) { this->ag = ag; }
2024-04-03 21:26:04 +07:00
2024-04-07 16:39:01 +07:00
#ifdef ESP32
/**
2024-04-07 16:39:01 +07:00
* @brief Construct a new Ag Wi Fi Connector:: Ag Wi Fi Connector object
*
2024-04-07 16:39:01 +07:00
* @param disp OledDisplay
* @param log Stream
* @param sm StateMachine
*/
WifiConnector::WifiConnector(OledDisplay &disp, Stream &log, StateMachine &sm,
Configuration &config)
: PrintLog(log, "WifiConnector"), disp(disp), sm(sm), config(config) {}
2024-04-07 16:39:01 +07:00
#else
WifiConnector::WifiConnector(Stream &log) : PrintLog(log, "WiFiConnector") {}
#endif
WifiConnector::~WifiConnector() {}
2024-04-03 21:26:04 +07:00
/**
* @brief Connection to WIFI AP process. Just call one times
*
* @return true Success
* @return false Failure
*/
2024-04-07 16:39:01 +07:00
bool WifiConnector::connect(void) {
2024-04-03 21:26:04 +07:00
if (wifi == NULL) {
wifi = new WiFiManager();
if (wifi == NULL) {
logError("Create 'WiFiManger' failed");
return false;
}
}
WIFI()->setConfigPortalBlocking(false);
WIFI()->setConnectTimeout(15);
2024-04-04 10:36:59 +07:00
WIFI()->setTimeout(WIFI_CONNECT_COUNTDOWN_MAX);
2024-04-03 21:26:04 +07:00
2024-04-07 16:39:01 +07:00
#ifdef ESP32
2024-04-03 21:26:04 +07:00
WIFI()->setAPCallback([this](WiFiManager *obj) { _wifiApCallback(); });
WIFI()->setSaveConfigCallback([this]() { _wifiSaveConfig(); });
WIFI()->setSaveParamsCallback([this]() { _wifiSaveParamCallback(); });
2024-04-07 16:39:01 +07:00
if (ag->isOne()) {
2024-04-03 21:26:04 +07:00
disp.setText("Connecting to", "WiFi", "...");
} else {
logInfo("Connecting to WiFi...");
}
ssid = "airgradient-" + ag->deviceId();
2024-04-07 16:39:01 +07:00
#else
ssid = "AG-" + String(ESP.getChipId(), HEX);
#endif
WIFI()->setConfigPortalTimeout(WIFI_CONNECT_COUNTDOWN_MAX);
WiFiManagerParameter postToAg("chbPostToAg",
"Prevent Connection to AirGradient Server", "T",
2, "type=\"checkbox\" ", WFM_LABEL_AFTER);
WIFI()->addParameter(&postToAg);
WiFiManagerParameter postToAgInfo(
"<p>Prevent connection to the AirGradient Server. Important: Only enable "
"it if you are sure you don't want to use any AirGradient cloud "
"features. As a result you will not receive automatic firmware updates "
"and your data will not reach the AirGradient dashboard.</p>");
WIFI()->addParameter(&postToAgInfo);
2024-04-03 21:26:04 +07:00
WIFI()->autoConnect(ssid.c_str(), WIFI_HOTSPOT_PASSWORD_DEFAULT);
2024-04-04 10:36:59 +07:00
2024-04-07 16:39:01 +07:00
#ifdef ESP32
2024-04-04 10:36:59 +07:00
// Task handle WiFi connection.
2024-04-03 21:26:04 +07:00
xTaskCreate(
[](void *obj) {
2024-04-07 16:39:01 +07:00
WifiConnector *connector = (WifiConnector *)obj;
2024-04-03 21:26:04 +07:00
while (connector->_wifiConfigPortalActive()) {
connector->_wifiProcess();
}
vTaskDelete(NULL);
},
"wifi_cfg", 4096, this, 10, NULL);
/** Wait for WiFi connect and show LED, display status */
uint32_t dispPeriod = millis();
uint32_t ledPeriod = millis();
bool clientConnectChanged = false;
AgStateMachineState stateOld = sm.getDisplayState();
while (WIFI()->getConfigPortalActive()) {
2024-04-04 10:36:59 +07:00
/** LED animatoin and display update content */
2024-04-03 21:26:04 +07:00
if (WiFi.isConnected() == false) {
/** Display countdown */
2024-04-04 10:36:59 +07:00
uint32_t ms;
2024-04-07 16:39:01 +07:00
if (ag->isOne()) {
2024-04-04 10:36:59 +07:00
ms = (uint32_t)(millis() - dispPeriod);
2024-04-03 21:26:04 +07:00
if (ms >= 1000) {
dispPeriod = millis();
sm.displayHandle();
} else {
if (stateOld != sm.getDisplayState()) {
stateOld = sm.getDisplayState();
sm.displayHandle();
}
}
}
/** LED animations */
ms = (uint32_t)(millis() - ledPeriod);
if (ms >= 100) {
ledPeriod = millis();
2024-04-07 16:39:01 +07:00
sm.handleLeds();
2024-04-03 21:26:04 +07:00
}
/** Check for client connect to change led color */
bool clientConnected = wifiClientConnected();
if (clientConnected != clientConnectChanged) {
clientConnectChanged = clientConnected;
if (clientConnectChanged) {
2024-04-07 16:39:01 +07:00
sm.handleLeds(AgStateMachineWiFiManagerPortalActive);
2024-04-03 21:26:04 +07:00
} else {
sm.ledAnimationInit();
2024-04-07 16:39:01 +07:00
sm.handleLeds(AgStateMachineWiFiManagerMode);
if (ag->isOne()) {
2024-04-03 21:26:04 +07:00
sm.displayHandle(AgStateMachineWiFiManagerMode);
}
}
}
}
2024-04-04 10:36:59 +07:00
delay(1); // avoid watchdog timer reset.
2024-04-03 21:26:04 +07:00
}
/** Show display wifi connect result failed */
if (WiFi.isConnected() == false) {
2024-04-07 16:39:01 +07:00
sm.handleLeds(AgStateMachineWiFiManagerConnectFailed);
if (ag->isOne()) {
2024-04-03 21:26:04 +07:00
sm.displayHandle(AgStateMachineWiFiManagerConnectFailed);
}
delay(6000);
} else {
2024-04-04 10:36:59 +07:00
hasConfig = true;
2024-04-07 16:39:01 +07:00
logInfo("WiFi Connected: " + WiFi.SSID() + " IP: " + localIpStr());
if (hasPortalConfig) {
String result = String(postToAg.getValue());
logInfo("Setting postToAirGradient set from " +
String(config.isPostDataToAirGradient() ? "True" : "False") +
String(" to ") + String(result != "T" ? "True" : "False") +
String(" successful"));
config.setPostToAirGradient(result != "T");
}
hasPortalConfig = false;
2024-04-03 21:26:04 +07:00
}
2024-04-07 16:39:01 +07:00
#else
_wifiProcess();
#endif
2024-04-04 10:36:59 +07:00
return true;
2024-04-03 21:26:04 +07:00
}
/**
* @brief Disconnect to current connected WiFi AP
*
*/
2024-04-07 16:39:01 +07:00
void WifiConnector::disconnect(void) {
if (WiFi.isConnected()) {
logInfo("Disconnect");
WiFi.disconnect();
}
}
2024-04-07 16:39:01 +07:00
#ifdef ESP32
#else
void WifiConnector::displayShowText(String ln1, String ln2, String ln3) {
char buf[9];
ag->display.clear();
ag->display.setCursor(1, 1);
ag->display.setText(ln1);
ag->display.setCursor(1, 19);
ag->display.setText(ln2);
ag->display.setCursor(1, 37);
ag->display.setText(ln3);
ag->display.show();
delay(100);
}
#endif
/**
* @brief Has wifi STA connected to WIFI softAP (this device)
*
* @return true Connected
* @return false Not connected
*/
2024-04-07 16:39:01 +07:00
bool WifiConnector::wifiClientConnected(void) {
2024-04-03 21:26:04 +07:00
return WiFi.softAPgetStationNum() ? true : false;
}
2024-04-07 16:39:01 +07:00
#ifdef ESP32
/**
* @brief Handle WiFiManage softAP setup completed callback
*
*/
2024-04-07 16:39:01 +07:00
void WifiConnector::_wifiApCallback(void) {
2024-04-03 21:26:04 +07:00
sm.displayWiFiConnectCountDown(WIFI_CONNECT_COUNTDOWN_MAX);
sm.setDisplayState(AgStateMachineWiFiManagerMode);
2024-04-04 10:36:59 +07:00
sm.ledAnimationInit();
2024-04-07 16:39:01 +07:00
sm.handleLeds(AgStateMachineWiFiManagerMode);
2024-04-03 21:26:04 +07:00
}
/**
* @brief Handle WiFiManager save configuration callback
*
*/
2024-04-07 16:39:01 +07:00
void WifiConnector::_wifiSaveConfig(void) {
2024-04-03 21:26:04 +07:00
sm.setDisplayState(AgStateMachineWiFiManagerStaConnected);
2024-04-07 16:39:01 +07:00
sm.handleLeds(AgStateMachineWiFiManagerStaConnected);
2024-04-03 21:26:04 +07:00
}
/**
* @brief Handle WiFiManager save parameter callback
*
*/
2024-04-07 16:39:01 +07:00
void WifiConnector::_wifiSaveParamCallback(void) {
2024-04-03 21:26:04 +07:00
sm.ledAnimationInit();
2024-04-07 16:39:01 +07:00
sm.handleLeds(AgStateMachineWiFiManagerStaConnecting);
2024-04-03 21:26:04 +07:00
sm.setDisplayState(AgStateMachineWiFiManagerStaConnecting);
hasPortalConfig = true;
2024-04-03 11:40:46 +07:00
}
2024-04-03 21:26:04 +07:00
/**
* @brief Check that WiFiManager Configure portal active
*
* @return true Active
* @return false Not-Active
*/
2024-04-07 16:39:01 +07:00
bool WifiConnector::_wifiConfigPortalActive(void) {
2024-04-03 21:26:04 +07:00
return WIFI()->getConfigPortalActive();
}
2024-04-07 16:39:01 +07:00
#endif
/**
* @brief Process WiFiManager connection
*
*/
2024-04-07 16:39:01 +07:00
void WifiConnector::_wifiProcess() {
#ifdef ESP32
WIFI()->process();
#else
int count = WIFI_CONNECT_COUNTDOWN_MAX;
displayShowText(String(WIFI_CONNECT_COUNTDOWN_MAX) + " sec", "SSID:", ssid);
while (WIFI()->getConfigPortalActive()) {
WIFI()->process();
2024-04-07 17:01:54 +07:00
2024-04-07 16:39:01 +07:00
uint32_t lastTime = millis();
uint32_t ms = (uint32_t)(millis() - lastTime);
if (ms >= 1000) {
lastTime = millis();
displayShowText(String(count) + " sec", "SSID:", ssid);
count--;
// Timeout
if (count == 0) {
break;
}
}
}
if (!WiFi.isConnected()) {
displayShowText("Booting", "offline", "mode");
Serial.println("failed to connect and hit timeout");
delay(2500);
2024-04-07 17:01:54 +07:00
} else {
hasConfig = true;
2024-04-07 16:39:01 +07:00
}
#endif
}
2024-04-04 10:36:59 +07:00
/**
* @brief Handle and reconnect WiFi
*
*/
2024-04-07 16:39:01 +07:00
void WifiConnector::handle(void) {
2024-04-04 10:36:59 +07:00
// Ignore if WiFi is not configured
if (hasConfig == false) {
return;
}
if (WiFi.isConnected()) {
lastRetry = millis();
return;
}
/** Retry connect WiFi each 10sec */
uint32_t ms = (uint32_t)(millis() - lastRetry);
if (ms >= 10000) {
lastRetry = millis();
WiFi.reconnect();
// Serial.printf("Re-Connect WiFi\r\n");
logInfo("Re-Connect WiFi");
}
}
/**
* @brief Is WiFi connected
*
* @return true Connected
* @return false Disconnected
*/
2024-04-07 16:39:01 +07:00
bool WifiConnector::isConnected(void) { return WiFi.isConnected(); }
/**
* @brief Reset WiFi configuretion and connection, disconnect wifi before call
* this method
*
*/
2024-04-07 16:39:01 +07:00
void WifiConnector::reset(void) { WIFI()->resetSettings(); }
/**
* @brief Get wifi RSSI
*
* @return int
*/
2024-04-07 16:39:01 +07:00
int WifiConnector::RSSI(void) { return WiFi.RSSI(); }
/**
* @brief Get WIFI IP as string format ex: 192.168.1.1
*
* @return String
*/
2024-04-07 16:39:01 +07:00
String WifiConnector::localIpStr(void) { return WiFi.localIP().toString(); }