You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

271 lines
8.3 KiB

//-----------------------------------------------------------------------------
// 2022 Ahoy, https://www.mikrocontroller.net/topic/525778
// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/
//-----------------------------------------------------------------------------
#if defined(ESP32) && defined(F)
#undef F
#define F(sl) (sl)
#endif
#include "ahoywifi.h"
// NTP CONFIG
#define NTP_PACKET_SIZE 48
//-----------------------------------------------------------------------------
ahoywifi::ahoywifi() {
mCnt = 0;
mConnected = false;
mInitNtp = true;
}
//-----------------------------------------------------------------------------
void ahoywifi::setup(settings_t *config, uint32_t *utcTimestamp) {
mConfig = config;
mUtcTimestamp = utcTimestamp;
#if !defined(FB_WIFI_OVERRIDDEN)
if(strncmp(mConfig->sys.stationSsid, FB_WIFI_SSID, 14) == 0)
setupAp();
#endif
#if !defined(AP_ONLY)
if(mConfig->valid)
setupStation();
#endif
#if defined(ESP8266)
wifiConnectHandler = WiFi.onStationModeGotIP(std::bind(&ahoywifi::onConnect, this, std::placeholders::_1));
wifiDisconnectHandler = WiFi.onStationModeDisconnected(std::bind(&ahoywifi::onDisconnect, this, std::placeholders::_1));
#else
WiFi.onEvent(std::bind(&ahoywifi::onWiFiEvent, this, std::placeholders::_1));
#endif
}
//-----------------------------------------------------------------------------
void ahoywifi::loop() {
#if !defined(AP_ONLY)
if(!mConnected) {
delay(100);
mCnt++;
if((mCnt % 50) == 0)
WiFi.disconnect();
else if((mCnt % 60) == 0) {
WiFi.reconnect();
mCnt = 0;
}
} else if(mInitNtp) {
getNtpTime();
mInitNtp = false;
}
mCnt = 0;
#endif
}
//-----------------------------------------------------------------------------
void ahoywifi::setupAp(void) {
DPRINTLN(DBG_VERBOSE, F("wifi::setupAp"));
IPAddress apIp(192, 168, 4, 1);
DBGPRINTLN(F("\n---------\nAhoyDTU Info:"));
DBGPRINT(F("Version: "));
DBGPRINTLN(String(VERSION_MAJOR) + F(".") + String(VERSION_MINOR) + F(".") + String(VERSION_PATCH));
DBGPRINT(F("Github Hash: "));
DBGPRINTLN(String(AUTO_GIT_HASH));
2 years ago
DBGPRINT(F("\n---------\nAP MODE\nSSID: "));
DBGPRINTLN(WIFI_AP_SSID);
2 years ago
DBGPRINT(F("PWD: "));
DBGPRINTLN(WIFI_AP_PWD);
DBGPRINTLN("IP Address: http://" + apIp.toString());
DBGPRINTLN(F("---------\n"));
WiFi.mode(WIFI_AP_STA);
WiFi.softAPConfig(apIp, apIp, IPAddress(255, 255, 255, 0));
WiFi.softAP(WIFI_AP_SSID, WIFI_AP_PWD);
mDns.start(53, "*", apIp);
}
//-----------------------------------------------------------------------------
void ahoywifi::setupStation(void) {
DPRINTLN(DBG_VERBOSE, F("wifi::setupStation"));
if(mConfig->sys.ip.ip[0] != 0) {
IPAddress ip(mConfig->sys.ip.ip);
IPAddress mask(mConfig->sys.ip.mask);
IPAddress dns1(mConfig->sys.ip.dns1);
IPAddress dns2(mConfig->sys.ip.dns2);
IPAddress gateway(mConfig->sys.ip.gateway);
if(!WiFi.config(ip, gateway, mask, dns1, dns2))
DPRINTLN(DBG_ERROR, F("failed to set static IP!"));
}
WiFi.begin(mConfig->sys.stationSsid, mConfig->sys.stationPwd);
if(String(mConfig->sys.deviceName) != "")
WiFi.hostname(mConfig->sys.deviceName);
2 years ago
DBGPRINT(F("connect to network '"));
DBGPRINT(mConfig->sys.stationSsid);
DBGPRINTLN(F("' ..."));
}
//-----------------------------------------------------------------------------
bool ahoywifi::getNtpTime(void) {
//DPRINTLN(DBG_VERBOSE, F("wifi::getNtpTime"));
if(!mConnected)
return false;
IPAddress timeServer;
uint8_t buf[NTP_PACKET_SIZE];
uint8_t retry = 0;
WiFi.hostByName(mConfig->ntp.addr, timeServer);
mUdp.begin(mConfig->ntp.port);
sendNTPpacket(timeServer);
while(retry++ < 5) {
int wait = 150;
while(--wait) {
if(NTP_PACKET_SIZE <= mUdp.parsePacket()) {
uint64_t secsSince1900;
mUdp.read(buf, NTP_PACKET_SIZE);
secsSince1900 = (buf[40] << 24);
secsSince1900 |= (buf[41] << 16);
secsSince1900 |= (buf[42] << 8);
secsSince1900 |= (buf[43] );
*mUtcTimestamp = secsSince1900 - 2208988800UL; // UTC time
DPRINTLN(DBG_INFO, "[NTP]: " + ah::getDateTimeStr(*mUtcTimestamp) + " UTC");
return true;
} else
delay(10);
}
}
DPRINTLN(DBG_INFO, F("[NTP]: getNtpTime failed"));
return false;
}
//-----------------------------------------------------------------------------
void ahoywifi::scanAvailNetworks(void) {
int n = WiFi.scanComplete();
if(n == -2)
WiFi.scanNetworks(true);
}
//-----------------------------------------------------------------------------
void ahoywifi::getAvailNetworks(JsonObject obj) {
JsonArray nets = obj.createNestedArray("networks");
int n = WiFi.scanComplete();
if(n > 0) {
int sort[n];
for (int i = 0; i < n; i++)
sort[i] = i;
for (int i = 0; i < n; i++)
for (int j = i + 1; j < n; j++)
if (WiFi.RSSI(sort[j]) > WiFi.RSSI(sort[i]))
std::swap(sort[i], sort[j]);
for (int i = 0; i < n; ++i) {
nets[i]["ssid"] = WiFi.SSID(sort[i]);
nets[i]["rssi"] = WiFi.RSSI(sort[i]);
}
WiFi.scanDelete();
}
}
//-----------------------------------------------------------------------------
void ahoywifi::sendNTPpacket(IPAddress& address) {
//DPRINTLN(DBG_VERBOSE, F("wifi::sendNTPpacket"));
uint8_t buf[NTP_PACKET_SIZE] = {0};
buf[0] = B11100011; // LI, Version, Mode
buf[1] = 0; // Stratum
buf[2] = 6; // Max Interval between messages in seconds
buf[3] = 0xEC; // Clock Precision
// bytes 4 - 11 are for Root Delay and Dispersion and were set to 0 by memset
buf[12] = 49; // four-byte reference ID identifying
buf[13] = 0x4E;
buf[14] = 49;
buf[15] = 52;
mUdp.beginPacket(address, 123); // NTP request, port 123
mUdp.write(buf, NTP_PACKET_SIZE);
mUdp.endPacket();
}
//-----------------------------------------------------------------------------
#if defined(ESP8266)
void ahoywifi::onConnect(const WiFiEventStationModeGotIP& event) {
if(!mConnected) {
mConnected = true;
DBGPRINTLN(F("\n[WiFi] Connected"));
WiFi.mode(WIFI_STA);
DBGPRINTLN(F("[WiFi] AP disabled"));
mDns.stop();
welcome(WiFi.localIP().toString() + F(" (Station)"));
}
}
//-------------------------------------------------------------------------
void ahoywifi::onDisconnect(const WiFiEventStationModeDisconnected& event) {
if(mConnected) {
mConnected = false;
DPRINTLN(DBG_INFO, "[WiFi] Connection Lost");
}
}
#else
//-------------------------------------------------------------------------
void ahoywifi::onWiFiEvent(WiFiEvent_t event) {
switch(event) {
case SYSTEM_EVENT_STA_GOT_IP:
if(!mConnected) {
delay(1000);
mConnected = true;
DBGPRINTLN(F("\n[WiFi] Connected"));
welcome(WiFi.localIP().toString() + F(" (Station)"));
WiFi.mode(WIFI_STA);
WiFi.begin();
DBGPRINTLN(F("[WiFi] AP disabled"));
mDns.stop();
}
break;
case SYSTEM_EVENT_STA_DISCONNECTED:
if(mConnected) {
mConnected = false;
DPRINTLN(DBG_INFO, "[WiFi] Connection Lost");
}
break;
default:
break;
}
}
#endif
//-----------------------------------------------------------------------------
void ahoywifi::welcome(String msg) {
DBGPRINTLN(F("\n\n--------------------------------"));
DBGPRINTLN(F("Welcome to AHOY!"));
DBGPRINT(F("\npoint your browser to http://"));
DBGPRINTLN(msg);
DBGPRINTLN(F("to configure your device"));
DBGPRINTLN(F("--------------------------------\n"));
}