#ifndef BLINKER_WLAN_H #define BLINKER_WLAN_H #if defined(ESP8266) || defined(ESP32) // #if defined(BLINKER_PRO) // #include "Blinker/BlinkerConfig.h" // #include "modules/ArduinoJson/ArduinoJson.h" // #if defined(ESP8266) // #include <ESP8266WiFi.h> // #elif defined(ESP32) // #include <WiFi.h> // #endif // #include <EEPROM.h> // static WiFiServer *_server; // static WiFiClient _client; // static IPAddress apIP(192, 168, 4, 1); // #if defined(ESP8266) // static IPAddress netMsk(255, 255, 255, 0); // #endif #if ARDUINO >= 100 #include <Arduino.h> #else #include <WProgram.h> #endif #include "Blinker/BlinkerConfig.h" #include "Blinker/BlinkerDebug.h" #include "Blinker/BlinkerUtility.h" #include "Functions/BlinkerWlan.h" #include "modules/ArduinoJson/ArduinoJson.h" #if defined(ESP8266) #include <ESP8266WiFi.h> #elif defined(ESP32) #include <WiFi.h> #endif #include <EEPROM.h> static WiFiServer *_server; static WiFiClient _client; static IPAddress apIP(192, 168, 4, 1); #if defined(ESP8266) static IPAddress netMsk(255, 255, 255, 0); #endif enum bwl_status_t { BWL_CONFIG_CKECK, BWL_CONFIG_FAIL, BWL_CONFIG_SUCCESS, BWL_CONNECTING, BWL_CONNECTED, BWL_DISCONNECTED, BWL_SMARTCONFIG_BEGIN, BWL_SMARTCONFIG_DONE, BWL_SMARTCONFIG_TIMEOUT, BWL_STACONFIG_BEGIN, BWL_APCONFIG_BEGIN, BWL_APCONFIG_DONE, BWL_APCONFIG_TIMEOUT, BWL_CONNECTED_CHECK, BWL_RESET }; class BlinkerWlan { public : BlinkerWlan() : _status(BWL_CONFIG_CKECK) {} bool checkConfig(); void loadConfig(char *_ssid, char *_pswd); void saveConfig(char *_ssid, char *_pswd); void deleteConfig(); void smartconfigBegin(uint16_t _time = 15000); bool smartconfigDone(); void connect(); bool connected(); void disconnect(); void reset(); bool run(); bwl_status_t status() { return _status; } void setType(const char* _type) { _deviceType = _type; #ifdef BLINKER_DEBUG_ALL BLINKER_LOG(BLINKER_F("API deviceType: "), _type); #endif } void softAPinit(); void serverClient(); void parseUrl(String data); void connectWiFi(String _ssid, String _pswd); void connectWiFi(const char* _ssid, const char* _pswd); // uint8_t status() { return _status; } private : protected : char *SSID; char *PSWD; const char* _deviceType; uint32_t connectTime; uint16_t timeout; bwl_status_t _status; uint32_t debugStatusTime; }; bool BlinkerWlan::checkConfig() { char ok[2 + 1]; EEPROM.begin(BLINKER_EEP_SIZE); EEPROM.get(BLINKER_EEP_ADDR_WLAN_CHECK, ok); EEPROM.commit(); EEPROM.end(); if (String(ok) != String("OK")) { BLINKER_LOG(BLINKER_F("wlan config check,fail")); _status = BWL_CONFIG_FAIL; return false; } else { BLINKER_LOG(BLINKER_F("wlan config check,success")); _status = BWL_CONFIG_SUCCESS; return true; } } void BlinkerWlan::loadConfig(char *_ssid, char *_pswd) { char loadssid[BLINKER_SSID_SIZE]; char loadpswd[BLINKER_PSWD_SIZE]; EEPROM.begin(BLINKER_EEP_SIZE); EEPROM.get(BLINKER_EEP_ADDR_SSID, loadssid); EEPROM.get(BLINKER_EEP_ADDR_PSWD, loadpswd); // char ok[2 + 1]; // EEPROM.get(EEP_ADDR_WIFI_CFG + BLINKER_SSID_SIZE + BLINKER_PSWD_SIZE, ok); EEPROM.commit(); EEPROM.end(); strcpy(_ssid, loadssid); strcpy(_pswd, loadpswd); BLINKER_LOG(BLINKER_F("SSID: "), _ssid, BLINKER_F(" PASWD: "), _pswd); } void BlinkerWlan::saveConfig(char *_ssid, char *_pswd) { char loadssid[BLINKER_SSID_SIZE]; char loadpswd[BLINKER_PSWD_SIZE]; memcpy(loadssid, _ssid, BLINKER_SSID_SIZE); memcpy(loadpswd, _pswd, BLINKER_PSWD_SIZE); EEPROM.begin(BLINKER_EEP_SIZE); EEPROM.put(BLINKER_EEP_ADDR_SSID, loadssid); EEPROM.put(BLINKER_EEP_ADDR_PSWD, loadpswd); char ok[2 + 1] = "OK"; EEPROM.put(BLINKER_EEP_ADDR_WLAN_CHECK, ok); EEPROM.commit(); EEPROM.end(); BLINKER_LOG(BLINKER_F("Save wlan config")); } void BlinkerWlan::deleteConfig() { char ok[3] = {0}; EEPROM.begin(BLINKER_EEP_SIZE); // for (int i = BLINKER_EEP_ADDR_WLAN_CHECK; i < BLINKER_WLAN_CHECK_SIZE; i++) // EEPROM.write(i, 0); EEPROM.put(BLINKER_EEP_ADDR_WLAN_CHECK, ok); EEPROM.commit(); EEPROM.end(); BLINKER_LOG(BLINKER_F("Erase wlan config")); } void BlinkerWlan::smartconfigBegin(uint16_t _time) { WiFi.mode(WIFI_STA); delay(100); String softAP_ssid = STRING_format(_deviceType) + "_" + macDeviceName(); #if defined(ESP8266) WiFi.hostname(softAP_ssid); #elif defined(ESP32) WiFi.setHostname(softAP_ssid.c_str()); #endif WiFi.beginSmartConfig(); connectTime = millis(); timeout = _time; _status = BWL_SMARTCONFIG_BEGIN; BLINKER_LOG(BLINKER_F("Wait for Smartconfig")); } bool BlinkerWlan::smartconfigDone() { if (WiFi.smartConfigDone()) { // WiFi.setAutoConnect(true); // WiFi.setAutoReconnect(true); connectTime = millis(); _status = BWL_SMARTCONFIG_DONE; BLINKER_LOG(BLINKER_F("SmartConfig Success")); #if defined(ESP8266) BLINKER_LOG(BLINKER_F("SSID: "), WiFi.SSID(), BLINKER_F(" PSWD: "), WiFi.psk()); // WiFi.begin(WiFi.SSID().c_str(), WiFi.psk().c_str()); connectWiFi(WiFi.SSID().c_str(), WiFi.psk().c_str()); #endif return true; } else { return false; } } void BlinkerWlan::connect() { switch (_status) { case BWL_CONFIG_SUCCESS : // WiFi.setAutoConnect(false); // WiFi.setAutoReconnect(true); SSID = (char*)malloc(BLINKER_SSID_SIZE*sizeof(char)); PSWD = (char*)malloc(BLINKER_PSWD_SIZE*sizeof(char)); loadConfig(SSID, PSWD); // WiFi.begin(SSID, PSWD); connectWiFi(SSID, PSWD); free(SSID); free(PSWD); _status = BWL_CONNECTING; break; case BWL_DISCONNECTED : if (millis() - connectTime > 30000 && WiFi.status() != WL_CONNECTED) { BLINKER_LOG(BLINKER_F("status: "), WiFi.status()); disconnect(); // SSID = (char*)malloc(BLINKER_SSID_SIZE*sizeof(char)); // PSWD = (char*)malloc(BLINKER_PSWD_SIZE*sizeof(char)); // WiFi.reconnect(); char _ssid_[BLINKER_SSID_SIZE]; char _pswd_[BLINKER_PSWD_SIZE]; loadConfig(_ssid_, _pswd_); connectWiFi(_ssid_, _pswd_); // WiFi.setAutoConnect(false); // WiFi.setAutoReconnect(true); // free(SSID); // free(PSWD); connectTime = millis(); BLINKER_LOG(BLINKER_F("connecting BWL_DISCONNECTED")); BLINKER_LOG(BLINKER_F("_ssid_: "), _ssid_, BLINKER_F(" _pswd_: "), _pswd_); } else if(WiFi.status() == WL_CONNECTED) { _status = BWL_CONNECTED; } break; } } bool BlinkerWlan::connected() { switch (_status) { case BWL_SMARTCONFIG_DONE : if (WiFi.status() != WL_CONNECTED) { if (millis() - connectTime > 15000) { BLINKER_LOG(BLINKER_F("smartConfig time out")); WiFi.stopSmartConfig(); _status = BWL_SMARTCONFIG_TIMEOUT; } return false; } else if (WiFi.status() == WL_CONNECTED) { // WiFi.stopSmartConfig(); IPAddress deviceIP = WiFi.localIP(); BLINKER_LOG(BLINKER_F("WiFi connected")); BLINKER_LOG(BLINKER_F("IP address: ")); BLINKER_LOG(deviceIP); BLINKER_LOG(BLINKER_F("SSID: "), WiFi.SSID(), BLINKER_F(" PSWD: "), WiFi.psk()); SSID = (char*)malloc(BLINKER_SSID_SIZE*sizeof(char)); PSWD = (char*)malloc(BLINKER_PSWD_SIZE*sizeof(char)); memcpy(SSID,"\0",BLINKER_SSID_SIZE); memcpy(SSID,WiFi.SSID().c_str(),BLINKER_SSID_SIZE); memcpy(PSWD,"\0",BLINKER_PSWD_SIZE); memcpy(PSWD,WiFi.psk().c_str(),BLINKER_PSWD_SIZE); saveConfig(SSID, PSWD); free(SSID); free(PSWD); // WiFi.setAutoConnect(true); // WiFi.setAutoReconnect(true); _status = BWL_CONNECTED_CHECK; BLINKER_LOG_FreeHeap_ALL(); return true; } // break; case BWL_APCONFIG_DONE : if (WiFi.status() != WL_CONNECTED) { if (millis() - connectTime > 15000) { BLINKER_LOG(BLINKER_F("APConfig time out")); // WiFi.stopSmartConfig(); _status = BWL_APCONFIG_TIMEOUT; } return false; } else if (WiFi.status() == WL_CONNECTED) { IPAddress deviceIP = WiFi.localIP(); BLINKER_LOG(BLINKER_F("WiFi connected")); BLINKER_LOG(BLINKER_F("IP address: ")); BLINKER_LOG(deviceIP); BLINKER_LOG(BLINKER_F("SSID: "), WiFi.SSID(), BLINKER_F(" PSWD: "), WiFi.psk()); // SSID = (char*)malloc(BLINKER_SSID_SIZE*sizeof(char)); // PSWD = (char*)malloc(BLINKER_PSWD_SIZE*sizeof(char)); // memcpy(SSID,"\0",BLINKER_SSID_SIZE); // memcpy(SSID,WiFi.SSID().c_str(),BLINKER_SSID_SIZE); // memcpy(PSWD,"\0",BLINKER_PSWD_SIZE); // memcpy(PSWD,WiFi.psk().c_str(),BLINKER_PSWD_SIZE); saveConfig(SSID, PSWD); free(SSID); free(PSWD); // WiFi.setAutoConnect(true); // WiFi.setAutoReconnect(true); _status = BWL_CONNECTED_CHECK; return true; } break; case BWL_CONNECTING : if (WiFi.status() == WL_CONNECTED) { IPAddress deviceIP = WiFi.localIP(); BLINKER_LOG(BLINKER_F("WiFi connected")); BLINKER_LOG(BLINKER_F("IP address: ")); BLINKER_LOG(deviceIP); BLINKER_LOG(BLINKER_F("SSID: "), WiFi.SSID(), BLINKER_F(" PSWD: "), WiFi.psk()); _status = BWL_CONNECTED_CHECK; return true; } else if (WiFi.status() != WL_CONNECTED) { return false; } case BWL_CONNECTED_CHECK : // if (WiFi.status() != WL_CONNECTED) // _status = BWL_DISCONNECTED; if (WiFi.status() == WL_CONNECTED) { return true; } else { _status = BWL_DISCONNECTED; return false; } case BWL_RESET : return false; default : if (WiFi.status() == WL_CONNECTED) { IPAddress deviceIP = WiFi.localIP(); BLINKER_LOG(BLINKER_F("WiFi connected")); BLINKER_LOG(BLINKER_F("IP address: ")); BLINKER_LOG(deviceIP); BLINKER_LOG(BLINKER_F("SSID: "), WiFi.SSID(), BLINKER_F(" PSWD: "), WiFi.psk()); _status = BWL_CONNECTED_CHECK; return true; } return false; } return false; } void BlinkerWlan::disconnect() { WiFi.disconnect(); delay(100); _status = BWL_DISCONNECTED; BLINKER_LOG(BLINKER_F("WiFi disconnected")); } void BlinkerWlan::reset() { disconnect(); _status = BWL_RESET; } void BlinkerWlan::softAPinit() { _server = new WiFiServer(80); WiFi.mode(WIFI_AP); String softAP_ssid = STRING_format(_deviceType) + "_" + macDeviceName(); #if defined(ESP8266) WiFi.hostname(softAP_ssid); #elif defined(ESP32) WiFi.setHostname(softAP_ssid.c_str()); #endif #if defined(ESP8266) WiFi.softAPConfig(apIP, apIP, netMsk); #elif defined(ESP32) WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0)); #endif WiFi.softAP(softAP_ssid.c_str(), "12345678"); delay(100); _server->begin(); BLINKER_LOG(BLINKER_F("AP IP address: "), WiFi.softAPIP()); BLINKER_LOG(BLINKER_F("HTTP _server started")); BLINKER_LOG(String("URL: http://" + WiFi.softAPIP())); _status = BWL_APCONFIG_BEGIN; BLINKER_LOG(BLINKER_F("Wait for APConfig")); } void BlinkerWlan::serverClient() { if (!_client) { _client = _server->available(); } else { // if (_client.status() == CLOSED) if (!_client.connected()) { _client.stop(); BLINKER_LOG(BLINKER_F("Connection closed on _client")); } else { if (_client.available()) { String data = _client.readStringUntil('\r'); // data = data.substring(4, data.length() - 9); _client.flush(); // BLINKER_LOG("clientData: ", data); if (STRING_contains_string(data, "ssid") && STRING_contains_string(data, "pswd")) { String msg = BLINKER_F("{\"hello\":\"world\"}"); String s= BLINKER_F("HTTP/1.1 200 OK\r\nContent-Type: application/json;charset=utf-8\r\n"); s += BLINKER_F("Content-Length: "); s += String(msg.length()); s += BLINKER_F("\r\nConnection: Keep Alive\r\n\r\n"); s += msg; s += BLINKER_F("\r\n"); _client.print(s); _client.stop(); parseUrl(data); } } } } } void BlinkerWlan::parseUrl(String data) { BLINKER_LOG(BLINKER_F("APCONFIG data: "), data); DynamicJsonBuffer jsonBuffer; JsonObject& wifi_data = jsonBuffer.parseObject(data); if (!wifi_data.success()) { return; } String _ssid = wifi_data["ssid"]; String _pswd = wifi_data["pswd"]; BLINKER_LOG(BLINKER_F("ssid: "), _ssid); BLINKER_LOG(BLINKER_F("pswd: "), _pswd); free(_server); SSID = (char*)malloc(BLINKER_SSID_SIZE*sizeof(char)); PSWD = (char*)malloc(BLINKER_PSWD_SIZE*sizeof(char)); strcpy(SSID, _ssid.c_str()); strcpy(PSWD, _pswd.c_str()); connectWiFi(_ssid, _pswd); connectTime = millis(); _status = BWL_APCONFIG_DONE; BLINKER_LOG(BLINKER_F("APConfig Success")); } void BlinkerWlan::connectWiFi(String _ssid, String _pswd) { connectWiFi(_ssid.c_str(), _pswd.c_str()); } void BlinkerWlan::connectWiFi(const char* _ssid, const char* _pswd) { uint32_t connectTime = millis(); BLINKER_LOG(BLINKER_F("Connecting to "), _ssid); WiFi.mode(WIFI_STA); String _hostname = STRING_format(_deviceType) + "_" + macDeviceName(); #if defined(ESP8266) WiFi.hostname(_hostname); #elif defined(ESP32) WiFi.setHostname(_hostname.c_str()); #endif if (_pswd && strlen(_pswd)) { WiFi.begin(_ssid, _pswd); } else { WiFi.begin(_ssid); } // while (WiFi.status() != WL_CONNECTED) { // ::delay(50); // if (millis() - connectTime > BLINKER_CONNECT_TIMEOUT_MS && WiFi.status() != WL_CONNECTED) { // connectTime = millis(); // BLINKER_LOG(("WiFi connect timeout, please check ssid and pswd!")); // BLINKER_LOG(("Retring WiFi connect again!")); // } // } // BLINKER_LOG(("Connected")); // IPAddress myip = WiFi.localIP(); // BLINKER_LOG(("Your IP is: "), myip); // mDNSInit(); } bool BlinkerWlan::run() { // if (millis() - debugStatusTime > 10000) { // debugStatusTime = millis(); // BLINKER_LOG_ALL("WLAN status: ", _status); // } switch (_status) { case BWL_CONFIG_CKECK : checkConfig(); break; case BWL_CONFIG_FAIL : #if defined(BLINKER_ESP_SMARTCONFIG) smartconfigBegin(); #elif defined(BLINKER_APCONFIG) softAPinit(); #endif break; case BWL_CONFIG_SUCCESS : connect(); break; case BWL_CONNECTING : return connected(); break; case BWL_CONNECTED : return connected(); break; case BWL_DISCONNECTED : connect(); break; case BWL_SMARTCONFIG_BEGIN : smartconfigDone(); break; case BWL_SMARTCONFIG_DONE : return connected(); break; case BWL_SMARTCONFIG_TIMEOUT : _status = BWL_CONFIG_FAIL; break; case BWL_STACONFIG_BEGIN : connect(); break; case BWL_APCONFIG_BEGIN : serverClient(); break; case BWL_APCONFIG_DONE : return connected(); break; case BWL_APCONFIG_TIMEOUT : _status = BWL_CONFIG_FAIL; break; case BWL_CONNECTED_CHECK : return connected(); break; case BWL_RESET: break; default : break; } return false; } // #endif #endif #endif