Browse Source

fix #472 refactored ahoyWifi class completely

-> now Ahoy opens an AP during boot. This will be closed once a station WiFi connection is established
improved NTP after boot, will be synced immediately after successful WiFi connection
pull/487/head
lumapu 2 years ago
parent
commit
7c6ab6792b
  1. 16
      src/app.cpp
  2. 18
      src/app.h
  3. 2
      src/config/settings.h
  4. 9
      src/hm/hmRadio.h
  5. 9
      src/utils/helper.cpp
  6. 3
      src/utils/helper.h
  7. 4
      src/web/web.cpp
  8. 231
      src/wifi/ahoywifi.cpp
  9. 41
      src/wifi/ahoywifi.h

16
src/app.cpp

@ -42,8 +42,7 @@ void app::setup(uint32_t timeout) {
mMqtt.setup(&mConfig->mqtt, mConfig->sys.deviceName, mVersion, mSys, &mUtcTimestamp, &mSunrise, &mSunset);
#endif
mWifi = new ahoywifi(mConfig);
mWifi->setup(timeout, mSettings.getValid());
mWifi.setup(mConfig, &mUtcTimestamp);
mPayload.setup(mSys);
mPayload.enableSerialDebug(mConfig->serial.debug);
@ -72,6 +71,10 @@ void app::loop(void) {
ah::Scheduler::loop();
#if !defined(AP_ONLY)
mWifi.loop();
#endif
mWeb->loop();
if (mFlagSendDiscoveryConfig) {
@ -198,19 +201,14 @@ void app::handleIntr(void) {
mSys->Radio.handleIntr();
}
//-----------------------------------------------------------------------------
bool app::getWifiApActive(void) {
return mWifi->getApActive();
}
//-----------------------------------------------------------------------------
void app::scanAvailNetworks(void) {
mWifi->scanAvailNetworks();
mWifi.scanAvailNetworks();
}
//-----------------------------------------------------------------------------
void app::getAvailNetworks(JsonObject obj) {
mWifi->getAvailNetworks(obj);
mWifi.getAvailNetworks(obj);
}

18
src/app.h

@ -84,15 +84,6 @@ class app : public ah::Scheduler {
return ret;
}
String getDateTimeStr(time_t t) {
char str[20];
if(0 == t)
sprintf(str, "n/a");
else
sprintf(str, "%04d-%02d-%02d %02d:%02d:%02d", year(t), month(t), day(t), hour(t), minute(t), second(t));
return String(str);
}
String getTimeStr(uint32_t offset = 0) {
char str[10];
if(0 == mUtcTimestamp)
@ -155,24 +146,19 @@ class app : public ah::Scheduler {
ESP.restart();
}
if (mUpdateNtp) {
mUpdateNtp = false;
mUtcTimestamp = mWifi->getNtpTime();
DPRINTLN(DBG_INFO, F("[NTP]: ") + getDateTimeStr(mUtcTimestamp) + F(" UTC"));
mWifi.getNtpTime();
}
}
void minuteTick(void) {
if(0 == mUtcTimestamp) {
if(!mWifi->getApActive())
mUpdateNtp = true;
}
}
void ntpUpdateTick(void) {
if (!mWifi->getApActive())
mUpdateNtp = true;
}
@ -203,7 +189,7 @@ class app : public ah::Scheduler {
bool mShowRebootRequest;
ahoywifi *mWifi;
ahoywifi mWifi;
web *mWeb;
PayloadType mPayload;
PubSerialType mPubSerial;

2
src/config/settings.h

@ -226,7 +226,7 @@ class settings {
private:
void loadDefaults(bool wifi = true) {
DPRINTLN(DBG_INFO, F("loadDefaults"));
DPRINTLN(DBG_VERBOSE, F("loadDefaults"));
if(wifi) {
snprintf(mCfg.sys.stationSsid, SSID_LEN, FB_WIFI_SSID);
snprintf(mCfg.sys.stationPwd, PWD_LEN, FB_WIFI_PWD);

9
src/hm/hmRadio.h

@ -139,14 +139,15 @@ class HmRadio {
mNrf24.setPALevel(ampPwr & 0x03);
mNrf24.startListening();
DPRINTLN(DBG_INFO, F("Radio Config:"));
mNrf24.printPrettyDetails();
mTxCh = setDefaultChannels();
if(!mNrf24.isChipConnected()) {
DPRINTLN(DBG_WARN, F("WARNING! your NRF24 module can't be reached, check the wiring"));
if(mNrf24.isChipConnected()) {
DPRINTLN(DBG_INFO, F("Radio Config:"));
mNrf24.printPrettyDetails();
}
else
DPRINTLN(DBG_WARN, F("WARNING! your NRF24 module can't be reached, check the wiring"));
}
void loop(void) {

9
src/utils/helper.cpp

@ -30,4 +30,13 @@ namespace ah {
double round3(double value) {
return (int)(value * 1000 + 0.5) / 1000.0;
}
String getDateTimeStr(time_t t) {
char str[20];
if(0 == t)
sprintf(str, "n/a");
else
sprintf(str, "%04d-%02d-%02d %02d:%02d:%02d", year(t), month(t), day(t), hour(t), minute(t), second(t));
return String(str);
}
}

3
src/utils/helper.h

@ -6,15 +6,18 @@
#ifndef __HELPER_H__
#define __HELPER_H__
#include <Arduino.h>
#include <cstdint>
#include <cstring>
#include <stdio.h>
#include <stdlib.h>
#include <TimeLib.h>
namespace ah {
void ip2Arr(uint8_t ip[], const char *ipStr);
void ip2Char(uint8_t ip[], char *str);
double round3(double value);
String getDateTimeStr(time_t t);
}
#endif /*__HELPER_H__*/

4
src/web/web.cpp

@ -664,10 +664,10 @@ void web::showJson(void) {
snprintf(val, 25, "[%.3f, \"%s\"]", iv->getValue(i), iv->getUnit(i));
modJson += String(topic) + ": " + String(val) + F(",\n");
}
modJson += F("\t\"last_msg\": \"") + mMain->getDateTimeStr(iv->ts) + F("\"\n\t},\n");
modJson += F("\t\"last_msg\": \"") + ah::getDateTimeStr(iv->ts) + F("\"\n\t},\n");
}
}
modJson += F("\"json_ts\": \"") + String(mMain->getDateTimeStr(mMain->mTimestamp)) + F("\"\n}\n");
modJson += F("\"json_ts\": \"") + String(ah::getDateTimeStr(mMain->mTimestamp)) + F("\"\n}\n");
mWeb->send(200, F("application/json"), modJson);
}

231
src/wifi/ahoywifi.cpp

@ -16,144 +16,84 @@
//-----------------------------------------------------------------------------
ahoywifi::ahoywifi(settings_t *config) {
mConfig = config;
mDns = new DNSServer();
mUdp = new WiFiUDP();
mWifiStationTimeout = 10;
wifiWasEstablished = false;
mNextTryTs = 0;
mApLastTick = 0;
mApActive = false;
ahoywifi::ahoywifi() {
mCnt = 0;
mConnected = false;
mInitNtp = true;
}
//-----------------------------------------------------------------------------
void ahoywifi::setup(uint32_t timeout, bool settingValid) {
//wifiConnectHandler = WiFi.onStationModeGotIP(std::bind(&ahoywifi::onConnect, this, std::placeholders::_1));
//wifiDisconnectHandler = WiFi.onStationModeDisconnected(std::bind(&ahoywifi::onDisconnect, this, std::placeholders::_1));
#ifdef FB_WIFI_OVERRIDDEN
mStationWifiIsDef = false;
#else
mStationWifiIsDef = (strncmp(mConfig->sys.stationSsid, FB_WIFI_SSID, 14) == 0);
void ahoywifi::setup(settings_t *config, uint32_t *utcTimestamp) {
char ipSta[16];
mConfig = config;
mUtcTimestamp = utcTimestamp;
#if !defined(FB_WIFI_OVERRIDDEN)
if(strncmp(mConfig->sys.stationSsid, FB_WIFI_SSID, 14) != 0)
setupAp();
#endif
mWifiStationTimeout = timeout;
#ifndef AP_ONLY
if(false == mApActive)
mApActive = (mStationWifiIsDef) ? true : setupStation(mWifiStationTimeout);
#if !defined(AP_ONLY)
setupStation();
ah::ip2Char(mConfig->sys.ip.ip, ipSta);
#endif
if(!settingValid) {
DPRINTLN(DBG_WARN, F("your settings are not valid! check [IP]/setup"));
mApActive = true;
mApLastTick = millis();
mNextTryTs = (millis() + (WIFI_AP_ACTIVE_TIME * 1000));
setupAp(WIFI_AP_SSID, WIFI_AP_PWD);
}
else {
DPRINTLN(DBG_INFO, F("\n\n----------------------------------------"));
DPRINTLN(DBG_INFO, F("Welcome to AHOY!"));
DPRINT(DBG_INFO, F("\npoint your browser to http://"));
if(mApActive)
DBGPRINTLN(F("192.168.4.1"));
else
DBGPRINTLN(WiFi.localIP().toString());
DPRINTLN(DBG_INFO, F("to configure your device"));
DPRINTLN(DBG_INFO, F("----------------------------------------\n"));
}
wifiConnectHandler = WiFi.onStationModeGotIP(std::bind(&ahoywifi::onConnect, this, std::placeholders::_1));
wifiDisconnectHandler = WiFi.onStationModeDisconnected(std::bind(&ahoywifi::onDisconnect, this, std::placeholders::_1));
}
//-----------------------------------------------------------------------------
bool ahoywifi::loop(void) {
if(mApActive) {
mDns->processNextRequest();
#ifndef AP_ONLY
if(ah::checkTicker(&mNextTryTs, (WIFI_AP_ACTIVE_TIME * 1000))) {
mApActive = (mStationWifiIsDef) ? true : setupStation(mWifiStationTimeout);
if(mApActive) {
if(strlen(WIFI_AP_PWD) < 8)
DPRINTLN(DBG_ERROR, F("password must be at least 8 characters long"));
mApLastTick = millis();
mNextTryTs = (millis() + (WIFI_AP_ACTIVE_TIME * 1000));
setupAp(WIFI_AP_SSID, WIFI_AP_PWD);
}
}
else {
if(millis() - mApLastTick > 10000) {
mApLastTick = millis();
uint8_t cnt = WiFi.softAPgetStationNum();
if(cnt > 0) {
DPRINTLN(DBG_INFO, String(cnt) + F(" client connected (no timeout)"));
mNextTryTs = (millis() + (WIFI_AP_ACTIVE_TIME * 1000));
}
else {
DBGPRINT(F("AP will be closed in "));
DBGPRINT(String((mNextTryTs - mApLastTick) / 1000));
DBGPRINTLN(F(" seconds"));
}
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
}
if((WiFi.status() != WL_CONNECTED) && wifiWasEstablished) {
if(!mApActive) {
DPRINTLN(DBG_INFO, "[WiFi]: Connection Lost");
mApActive = (mStationWifiIsDef) ? true : setupStation(mWifiStationTimeout);
}
}
return mApActive;
}
//-----------------------------------------------------------------------------
void ahoywifi::setupAp(const char *ssid, const char *pwd) {
DPRINTLN(DBG_VERBOSE, F("app::setupAp"));
void ahoywifi::setupAp(void) {
DPRINTLN(DBG_VERBOSE, F("wifi::setupAp"));
IPAddress apIp(192, 168, 4, 1);
DBGPRINTLN(F("\n---------\nAhoy Info:"));
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));
DBGPRINT(F("\n---------\nAP MODE\nSSID: "));
DBGPRINTLN(ssid);
DBGPRINTLN(WIFI_AP_SSID);
DBGPRINT(F("PWD: "));
DBGPRINTLN(pwd);
DBGPRINT(F("\nActive for: "));
DBGPRINT(String(WIFI_AP_ACTIVE_TIME));
DBGPRINTLN(F(" seconds"));
DBGPRINTLN(WIFI_AP_PWD);
DBGPRINTLN("IP Address: http://" + apIp.toString());
DBGPRINTLN(F("---------\n"));
DBGPRINTLN("\nIp Address: " + apIp[0] + apIp[1] + apIp[2] + apIp[3]);
DBGPRINTLN(F("\n---------\n"));
WiFi.mode(WIFI_AP);
WiFi.mode(WIFI_AP_STA);
WiFi.softAPConfig(apIp, apIp, IPAddress(255, 255, 255, 0));
WiFi.softAP(ssid, pwd);
WiFi.softAP(WIFI_AP_SSID, WIFI_AP_PWD);
mDns->start(53, "*", apIp);
mDns.start(53, "*", apIp);
}
//-----------------------------------------------------------------------------
bool ahoywifi::setupStation(uint32_t timeout) {
DPRINTLN(DBG_VERBOSE, F("app::setupStation"));
int32_t cnt;
bool startAp = false;
if(timeout >= 3)
cnt = (timeout - 3) / 2 * 10;
else {
timeout = 1;
cnt = 1;
}
WiFi.mode(WIFI_STA);
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);
@ -167,45 +107,14 @@ bool ahoywifi::setupStation(uint32_t timeout) {
if(String(mConfig->sys.deviceName) != "")
WiFi.hostname(mConfig->sys.deviceName);
delay(2000);
DBGPRINT(F("connect to network '"));
DBGPRINT(mConfig->sys.stationSsid);
DBGPRINTLN(F("' ..."));
while (WiFi.status() != WL_CONNECTED) {
delay(100);
if(cnt % 40 == 0)
DBGPRINTLN(".");
else
DBGPRINT(".");
if(timeout > 0) { // limit == 0 -> no limit
if(--cnt <= 0) {
if(WiFi.status() != WL_CONNECTED) {
startAp = true;
WiFi.disconnect();
}
delay(100);
break;
}
}
}
Serial.println(".");
if(false == startAp)
wifiWasEstablished = true;
delay(1000);
return startAp;
}
//-----------------------------------------------------------------------------
bool ahoywifi::getApActive(void) {
return mApActive;
}
//-----------------------------------------------------------------------------
time_t ahoywifi::getNtpTime(void) {
void ahoywifi::getNtpTime(void) {
//DPRINTLN(DBG_VERBOSE, F("wifi::getNtpTime"));
time_t date = 0;
IPAddress timeServer;
@ -213,16 +122,16 @@ time_t ahoywifi::getNtpTime(void) {
uint8_t retry = 0;
WiFi.hostByName(mConfig->ntp.addr, timeServer);
mUdp->begin(mConfig->ntp.port);
mUdp.begin(mConfig->ntp.port);
sendNTPpacket(timeServer);
while(retry++ < 5) {
int wait = 150;
while(--wait) {
if(NTP_PACKET_SIZE <= mUdp->parsePacket()) {
if(NTP_PACKET_SIZE <= mUdp.parsePacket()) {
uint64_t secsSince1900;
mUdp->read(buf, NTP_PACKET_SIZE);
mUdp.read(buf, NTP_PACKET_SIZE);
secsSince1900 = (buf[40] << 24);
secsSince1900 |= (buf[41] << 16);
secsSince1900 |= (buf[42] << 8);
@ -230,13 +139,14 @@ time_t ahoywifi::getNtpTime(void) {
date = secsSince1900 - 2208988800UL; // UTC time
break;
}
else
} else
delay(10);
}
}
return date;
*mUtcTimestamp = date;
DPRINTLN(DBG_INFO, F("[NTP]: ") + ah::getDateTimeStr(*mUtcTimestamp) + F(" UTC"));
}
@ -285,19 +195,42 @@ void ahoywifi::sendNTPpacket(IPAddress& address) {
buf[14] = 49;
buf[15] = 52;
mUdp->beginPacket(address, 123); // NTP request, port 123
mUdp->write(buf, NTP_PACKET_SIZE);
mUdp->endPacket();
mUdp.beginPacket(address, 123); // NTP request, port 123
mUdp.write(buf, NTP_PACKET_SIZE);
mUdp.endPacket();
}
//-----------------------------------------------------------------------------
/*void ahoywifi::onConnect(const WiFiEventStationModeGotIP& event) {
Serial.println("Connected to Wi-Fi.");
void ahoywifi::onConnect(const WiFiEventStationModeGotIP& event) {
if(!mConnected) {
mConnected = true;
DBGPRINTLN(F("\n[WiFi] Connected"));
WiFi.mode(WIFI_STA);
WiFi.begin();
DBGPRINTLN(F("[WiFi] AP disabled"));
mDns.stop();
welcome(WiFi.localIP().toString() + F(" (Station)"));
}
}
//-----------------------------------------------------------------------------
void ahoywifi::onDisconnect(const WiFiEventStationModeDisconnected& event) {
Serial.println("Disconnected from Wi-Fi.");
}*/
if(mConnected) {
mConnected = false;
DPRINTLN(DBG_INFO, "[WiFi] Connection Lost");
}
}
//-----------------------------------------------------------------------------
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"));
}

41
src/wifi/ahoywifi.h

@ -9,7 +9,6 @@
#include "../utils/dbg.h"
#include <Arduino.h>
#include <WiFiUdp.h>
#include <TimeLib.h>
#include <DNSServer.h>
#include "ESPAsyncWebServer.h"
@ -19,36 +18,32 @@ class app;
class ahoywifi {
public:
ahoywifi(settings_t *config);
~ahoywifi() {}
void setup(uint32_t timeout, bool settingValid);
bool loop(void);
void setupAp(const char *ssid, const char *pwd);
bool setupStation(uint32_t timeout);
bool getApActive(void);
time_t getNtpTime(void);
ahoywifi();
void setup(settings_t *config, uint32_t *utcTimestamp);
void loop(void);
void getNtpTime(void);
void scanAvailNetworks(void);
void getAvailNetworks(JsonObject obj);
private:
void setupAp(void);
void setupStation(void);
void sendNTPpacket(IPAddress& address);
//void onConnect(const WiFiEventStationModeGotIP& event);
//void onDisconnect(const WiFiEventStationModeDisconnected& event);
void onConnect(const WiFiEventStationModeGotIP& event);
void onDisconnect(const WiFiEventStationModeDisconnected& event);
void welcome(String msg);
settings_t *mConfig;
DNSServer *mDns;
WiFiUDP *mUdp; // for time server
//WiFiEventHandler wifiConnectHandler;
//WiFiEventHandler wifiDisconnectHandler;
uint32_t mWifiStationTimeout;
uint32_t mNextTryTs;
uint32_t mApLastTick;
bool mApActive;
bool wifiWasEstablished;
bool mStationWifiIsDef;
DNSServer mDns;
WiFiUDP mUdp; // for time server
WiFiEventHandler wifiConnectHandler;
WiFiEventHandler wifiDisconnectHandler;
bool mConnected, mInitNtp;
uint8_t mCnt;
uint32_t *mUtcTimestamp;
};
#endif /*__AHOYWIFI_H__*/

Loading…
Cancel
Save