Browse Source

improved stability

improved wifi initial connection - especially if station wifi is not available #509
removed new operators from web.h (reduce dynamic allocation)
improved sun calculation #515, #505
fixed wifi auto reconnect #509
added disable night communication flag to MQTT #505
changed MQTT publish of `available` and `available_text` to sunset #468
pull/518/head
lumapu 2 years ago
parent
commit
07bf947ff7
  1. 11
      src/CHANGES.md
  2. 51
      src/app.cpp
  3. 23
      src/app.h
  4. 2
      src/defines.h
  5. 9
      src/hm/hmRadio.h
  6. 5
      src/hm/hmSystem.h
  7. 1
      src/hm/payload.h
  8. 3
      src/publisher/pubMqtt.h
  9. 1
      src/web/RestApi.h
  10. 7
      src/web/html/index.html
  11. 5
      src/web/html/system.html
  12. 105
      src/web/web.h
  13. 101
      src/wifi/ahoywifi.cpp
  14. 12
      src/wifi/ahoywifi.h

11
src/CHANGES.md

@ -1,5 +1,14 @@
# Changelog
## 0.5.58
* improved stability
* improved wifi initial connection - especially if station wifi is not available
* removed new operators from web.h (reduce dynamic allocation)
* improved sun calculation #515, #505
* fixed wifi auto reconnect #509
* added disable night communication flag to MQTT #505
* changed MQTT publish of `available` and `available_text` to sunset #468
## 0.5.57
* improved stability
* added icons to index.html, added wifi-strength symbol on each page
@ -8,7 +17,7 @@
## 0.5.56
* factory reset formats entire little fs
* renamed sunrise / sunset on indext.html to start / stop communication
* renamed sunrise / sunset on index.html to start / stop communication
* show system information only if called directly from menu
* beautified system.html

51
src/app.cpp

@ -45,18 +45,13 @@ void app::setup() {
every(std::bind(&app::tickSend, this), mConfig->nrf.sendInterval);
#if !defined(AP_ONLY)
once(std::bind(&app::tickNtpUpdate, this), 2);
if((mConfig->sun.lat) && (mConfig->sun.lon)) {
mCalculatedTimezoneOffset = (int8_t)((mConfig->sun.lon >= 0 ? mConfig->sun.lon + 7.5 : mConfig->sun.lon - 7.5) / 15) * 3600;
once(std::bind(&app::tickCalcSunrise, this), 5);
}
#endif
if(mSys->Radio.isChipConnected()) {
mSys->addInverters(&mConfig->inst);
mPayload.setup(mSys);
mPayload.enableSerialDebug(mConfig->serial.debug);
}
else
if(!mSys->Radio.isChipConnected())
DPRINTLN(DBG_WARN, F("WARNING! your NRF24 module can't be reached, check the wiring"));
// when WiFi is in client mode, then enable mqtt broker
@ -95,8 +90,6 @@ void app::loop(void) {
mWifi.loop();
#endif
mWeb.loop();
mSys->Radio.loop();
yield();
@ -134,26 +127,46 @@ void app::loop(void) {
//-----------------------------------------------------------------------------
void app::tickNtpUpdate(void) {
uint32_t nxtTrig = 5; // default: check again in 5 sec
if (mWifi.getNtpTime())
if (mWifi.getNtpTime()) {
nxtTrig = 43200; // check again in 12 h
if((mSunrise == 0) && (mConfig->sun.lat) && (mConfig->sun.lon)) {
mCalculatedTimezoneOffset = (int8_t)((mConfig->sun.lon >= 0 ? mConfig->sun.lon + 7.5 : mConfig->sun.lon - 7.5) / 15) * 3600;
tickCalcSunrise();
}
}
once(std::bind(&app::tickNtpUpdate, this), nxtTrig);
}
//-----------------------------------------------------------------------------
void app::tickCalcSunrise(void) {
if (0 == mTimestamp) {
once(std::bind(&app::tickCalcSunrise, this), 5); // check again in 5 secs
return;
}
ah::calculateSunriseSunset(mTimestamp, mCalculatedTimezoneOffset, mConfig->sun.lat, mConfig->sun.lon, &mSunrise, &mSunset);
tickIVCommunication();
uint32_t nxtTrig = mTimestamp - ((mTimestamp - 10) % 86400) + 86400; // next midnight, -10 for safety that it is certain next day
uint32_t nxtTrig = mTimestamp - ((mTimestamp - 1) % 86400) + 86400; // next midnight, -10 for safety that it is certain next day
onceAt(std::bind(&app::tickCalcSunrise, this), nxtTrig);
if (mConfig->mqtt.broker[0] > 0) {
mMqtt.tickerSun(mSunrise, mSunset, mConfig->sun.offsetSec);
mMqtt.tickerSun(mSunrise, mSunset, mConfig->sun.offsetSec, mConfig->sun.disNightCom);
onceAt(std::bind(&PubMqttType::tickSunrise, &mMqtt), (mSunrise - mConfig->sun.offsetSec));
onceAt(std::bind(&PubMqttType::tickSunset, &mMqtt), (mSunset + mConfig->sun.offsetSec));
onceAt(std::bind(&PubMqttType::tickSunset, &mMqtt), mSunset);
}
}
//-----------------------------------------------------------------------------
void app::tickIVCommunication(void) {
mIVCommunicationOn = !mConfig->sun.disNightCom; // if sun.disNightCom is false, communication is always on
if (!mIVCommunicationOn) { // inverter communication only during the day
uint32_t nxtTrig;
if (mTimestamp < (mSunrise - mConfig->sun.offsetSec)) { // current time is before communication start, set next trigger to communication start
nxtTrig = mSunrise - mConfig->sun.offsetSec;
} else {
if (mTimestamp > (mSunset + mConfig->sun.offsetSec)) { // current time is past communication stop, nothing to do. Next update will be done at midnight by tickCalcSunrise
return;
} else { // current time lies within communication start/stop time, set next trigger to communication stop
mIVCommunicationOn = true;
nxtTrig = mSunset + mConfig->sun.offsetSec;
}
}
onceAt(std::bind(&app::tickIVCommunication, this), nxtTrig);
}
}
@ -163,7 +176,7 @@ void app::tickSend(void) {
DPRINTLN(DBG_WARN, "NRF24 not connected!");
return;
}
if ((mTimestamp > 0) && (!mConfig->sun.disNightCom || (mTimestamp >= (mSunrise - mConfig->sun.offsetSec) && mTimestamp <= (mSunset + mConfig->sun.offsetSec)))) { // Timestamp is set and (inverter communication only during the day if the option is activated and sunrise/sunset is set)
if (mIVCommunicationOn) {
if (!mSys->BufCtrl.empty()) {
if (mConfig->serial.debug)
DPRINTLN(DBG_DEBUG, F("recbuf not empty! #") + String(mSys->BufCtrl.getFill()));

23
src/app.h

@ -184,31 +184,12 @@ class app : public IApp, public ah::Scheduler {
}
void tickNtpUpdate(void);
void tickCalcSunrise(void);
void tickIVCommunication(void);
void tickSend(void);
void stats(void) {
DPRINTLN(DBG_VERBOSE, F("main.h:stats"));
#ifdef ESP8266
uint32_t free;
uint16_t max;
uint8_t frag;
ESP.getHeapStats(&free, &max, &frag);
#elif defined(ESP32)
uint32_t free;
uint32_t max;
uint8_t frag;
free = ESP.getFreeHeap();
max = ESP.getMaxAllocHeap();
frag = 0;
#endif
DPRINT(DBG_VERBOSE, F("free: ") + String(free));
DPRINT(DBG_VERBOSE, F(" - max: ") + String(max) + "%");
DPRINTLN(DBG_VERBOSE, F(" - frag: ") + String(frag));
}
bool mShowRebootRequest;
bool mIVCommunicationOn;
ahoywifi mWifi;
WebType mWeb;

2
src/defines.h

@ -13,7 +13,7 @@
//-------------------------------------
#define VERSION_MAJOR 0
#define VERSION_MINOR 5
#define VERSION_PATCH 57
#define VERSION_PATCH 58
//-------------------------------------
typedef struct {

9
src/hm/hmRadio.h

@ -151,8 +151,8 @@ class HmRadio {
}
void loop(void) {
DISABLE_IRQ;
if(mIrqRcvd) {
DISABLE_IRQ;
mIrqRcvd = false;
bool tx_ok, tx_fail, rx_ready;
mNrf24.whatHappened(tx_ok, tx_fail, rx_ready); // resets the IRQ pin to HIGH
@ -175,17 +175,15 @@ class HmRadio {
break;
}
mNrf24.flush_rx(); // drop the packet
}
else
RESTORE_IRQ;
}
}
void enableDebug() {
mSerialDebug = true;
}
void handleIntr(void) {
//DPRINTLN(DBG_VERBOSE, F("hmRadio.h:handleIntr"));
mIrqRcvd = true;
}
@ -267,7 +265,8 @@ class HmRadio {
}
bool switchRxCh(uint16_t addLoop = 0) {
//DPRINTLN(DBG_VERBOSE, F("hmRadio.h:switchRxCh"));
if(!mNrf24.isChipConnected())
return true;
mRxLoopCnt += addLoop;
if(mRxLoopCnt != 0) {
mRxLoopCnt--;

5
src/hm/hmSystem.h

@ -104,14 +104,15 @@ class HmSystem {
}
uint8_t getNumInverters(void) {
uint8_t num = 0;
/*uint8_t num = 0;
INVERTERTYPE *p;
for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) {
p = &mInverter[i];
if(p->config->serial.u64 != 0ULL)
num++;
}
return num;
return num;*/
return MAX_NUM_INVERTERS;
}
void enableDebug() {

1
src/hm/payload.h

@ -9,6 +9,7 @@
#include "../utils/dbg.h"
#include "../utils/crc.h"
#include "../utils/handler.h"
#include "../config/config.h"
#include <Arduino.h>
typedef struct {

3
src/publisher/pubMqtt.h

@ -91,11 +91,12 @@ class PubMqtt {
tickSunset();
}
void tickerSun(uint32_t sunrise, uint32_t sunset, uint32_t offs) {
void tickerSun(uint32_t sunrise, uint32_t sunset, uint32_t offs, bool disNightCom) {
publish("sunrise", String(sunrise).c_str(), true);
publish("sunset", String(sunset).c_str(), true);
publish("comm_start", String(sunrise - offs).c_str(), true);
publish("comm_stop", String(sunset + offs).c_str(), true);
publish("dis_night_comm", ((disNightCom) ? "true" : "false"), true);
}
void tickSunrise() {

1
src/web/RestApi.h

@ -353,6 +353,7 @@ class RestApi {
obj[F("ts_sunrise")] = mApp->getSunrise();
obj[F("ts_sunset")] = mApp->getSunset();
obj[F("ts_offset")] = mConfig->sun.offsetSec;
obj[F("disNightComm")] = mConfig->sun.disNightCom;
JsonArray inv = obj.createNestedArray(F("inverter"));
Inverter<> *iv;

7
src/web/html/index.html

@ -47,10 +47,11 @@
<div id="note">
<h3>Support this project:</h3>
<ul>
<li><a href="https://github.com/lumapu/ahoy/blob/main/src/CHANGES.md" target="_blank">Changelog</a></li>
<li>Discuss with us on <a href="https://discord.gg/WzhxEY62mB">Discord</a></li>
<li>Report <a href="https://github.com/lumapu/ahoy/issues" target="_blank">issues</a></li>
<li>Contribute to <a href="https://github.com/lumapu/ahoy/blob/main/User_Manual.md" target="_blank">documentation</a></li>
<li>Test <a href="https://github.com/lumapu/ahoy/actions/workflows/compile_development.yml" target="_blank">development firmware</a></li>
<li><a href="https://nightly.link/lumapu/ahoy/workflows/compile_development/development03/ahoydtu_dev.zip" target="_blank">Download</a> & Test development firmware, <a href="https://github.com/lumapu/ahoy/blob/development03/src/CHANGES.md" target="_blank">Changelog</a></li>
<li>make a <a href="https://paypal.me/lupusch" target="_blank">donation</a></li>
</ul>
<p class="lic">
@ -145,7 +146,7 @@
&& ((obj["ts_sunset"] + obj["ts_offset"]) > obj["ts_now"])) {
commInfo = "Polling inverter(s), will stop at " + (new Date((obj["ts_sunset"] + obj["ts_offset"]) * 1000).toLocaleString('de-DE'));
}
else {
else if(obj["disNightComm"]) {
commInfo = "Night time, no Communication to Inverter, ";
if(obj["ts_now"] > (obj["ts_sunrise"] - obj["ts_offset"])) {
commInfo += "stopped polling at " + (new Date((obj["ts_sunset"] + obj["ts_offset"]) * 1000).toLocaleString('de-DE'));
@ -176,6 +177,8 @@
avail = "available and is ";
if(false == i["is_producing"])
avail += "not ";
else
color = "#090";
avail += "producing";
}

5
src/web/html/system.html

@ -103,6 +103,7 @@
}
function parseIndex(obj) {
if(obj["ts_sunrise"] > 0) {
var h = div(["head", "p-2"]);
var r = div(["row"]);
r.appendChild(div(["col", "a-c"], "Sun"));
@ -113,9 +114,11 @@
genTabRow("Sunrise", new Date(obj["ts_sunrise"] * 1000).toLocaleString('de-DE')),
genTabRow("Sunset", new Date(obj["ts_sunset"] * 1000).toLocaleString('de-DE')),
genTabRow("Communication start", new Date((obj["ts_sunrise"] - obj["ts_offset"]) * 1000).toLocaleString('de-DE')),
genTabRow("Communication stop", new Date((obj["ts_sunset"] + obj["ts_offset"]) * 1000).toLocaleString('de-DE'))
genTabRow("Communication stop", new Date((obj["ts_sunset"] + obj["ts_offset"]) * 1000).toLocaleString('de-DE')),
genTabRow("Night Communication", ((obj["disNightComm"]) ? "disabled" : "enabled"))
);
}
}
function parse(obj) {
if(null != obj) {

105
src/web/web.h

@ -39,72 +39,59 @@ const char* const pinArgNames[] = {"pinCs", "pinCe", "pinIrq", "pinLed0", "pinLe
template<class HMSYSTEM>
class Web {
public:
Web(void) {
Web(void) : mWeb(80), mEvts("/events") {
mProtected = true;
mLogoutTimeout = 0;
memset(mSerialBuf, 0, WEB_SERIAL_BUF_SIZE);
mSerialBufFill = 0;
mWebSerialTicker = 0;
mWebSerialInterval = 1000; // [ms]
mSerialAddTime = true;
mSerialClientConnnected = false;
}
void setup(IApp *app, HMSYSTEM *sys, settings_t *config) {
mApp = app;
mSys = sys;
mConfig = config;
mWeb = new AsyncWebServer(80);
mEvts = new AsyncEventSource("/events");
DPRINTLN(DBG_VERBOSE, F("app::setup-begin"));
mWeb->begin();
DPRINTLN(DBG_VERBOSE, F("app::setup-on"));
mWeb->on("/", HTTP_GET, std::bind(&Web::onIndex, this, std::placeholders::_1));
mWeb->on("/login", HTTP_ANY, std::bind(&Web::onLogin, this, std::placeholders::_1));
mWeb->on("/logout", HTTP_GET, std::bind(&Web::onLogout, this, std::placeholders::_1));
mWeb->on("/style.css", HTTP_GET, std::bind(&Web::onCss, this, std::placeholders::_1));
mWeb->on("/api.js", HTTP_GET, std::bind(&Web::onApiJs, this, std::placeholders::_1));
mWeb->on("/favicon.ico", HTTP_GET, std::bind(&Web::onFavicon, this, std::placeholders::_1));
mWeb->onNotFound ( std::bind(&Web::showNotFound, this, std::placeholders::_1));
mWeb->on("/reboot", HTTP_ANY, std::bind(&Web::onReboot, this, std::placeholders::_1));
mWeb->on("/system", HTTP_ANY, std::bind(&Web::onSystem, this, std::placeholders::_1));
mWeb->on("/erase", HTTP_ANY, std::bind(&Web::showErase, this, std::placeholders::_1));
mWeb->on("/factory", HTTP_ANY, std::bind(&Web::showFactoryRst, this, std::placeholders::_1));
mWeb->on("/setup", HTTP_GET, std::bind(&Web::onSetup, this, std::placeholders::_1));
mWeb->on("/save", HTTP_ANY, std::bind(&Web::showSave, this, std::placeholders::_1));
mWeb->on("/live", HTTP_ANY, std::bind(&Web::onLive, this, std::placeholders::_1));
mWeb->on("/api1", HTTP_POST, std::bind(&Web::showWebApi, this, std::placeholders::_1));
mWeb.on("/", HTTP_GET, std::bind(&Web::onIndex, this, std::placeholders::_1));
mWeb.on("/login", HTTP_ANY, std::bind(&Web::onLogin, this, std::placeholders::_1));
mWeb.on("/logout", HTTP_GET, std::bind(&Web::onLogout, this, std::placeholders::_1));
mWeb.on("/style.css", HTTP_GET, std::bind(&Web::onCss, this, std::placeholders::_1));
mWeb.on("/api.js", HTTP_GET, std::bind(&Web::onApiJs, this, std::placeholders::_1));
mWeb.on("/favicon.ico", HTTP_GET, std::bind(&Web::onFavicon, this, std::placeholders::_1));
mWeb.onNotFound ( std::bind(&Web::showNotFound, this, std::placeholders::_1));
mWeb.on("/reboot", HTTP_ANY, std::bind(&Web::onReboot, this, std::placeholders::_1));
mWeb.on("/system", HTTP_ANY, std::bind(&Web::onSystem, this, std::placeholders::_1));
mWeb.on("/erase", HTTP_ANY, std::bind(&Web::showErase, this, std::placeholders::_1));
mWeb.on("/factory", HTTP_ANY, std::bind(&Web::showFactoryRst, this, std::placeholders::_1));
mWeb.on("/setup", HTTP_GET, std::bind(&Web::onSetup, this, std::placeholders::_1));
mWeb.on("/save", HTTP_ANY, std::bind(&Web::showSave, this, std::placeholders::_1));
mWeb.on("/live", HTTP_ANY, std::bind(&Web::onLive, this, std::placeholders::_1));
mWeb.on("/api1", HTTP_POST, std::bind(&Web::showWebApi, this, std::placeholders::_1));
#ifdef ENABLE_JSON_EP
mWeb->on("/json", HTTP_ANY, std::bind(&Web::showJson, this, std::placeholders::_1));
mWeb.on("/json", HTTP_ANY, std::bind(&Web::showJson, this, std::placeholders::_1));
#endif
#ifdef ENABLE_PROMETHEUS_EP
mWeb->on("/metrics", HTTP_ANY, std::bind(&Web::showMetrics, this, std::placeholders::_1));
mWeb.on("/metrics", HTTP_ANY, std::bind(&Web::showMetrics, this, std::placeholders::_1));
#endif
mWeb->on("/update", HTTP_GET, std::bind(&Web::onUpdate, this, std::placeholders::_1));
mWeb->on("/update", HTTP_POST, std::bind(&Web::showUpdate, this, std::placeholders::_1),
mWeb.on("/update", HTTP_GET, std::bind(&Web::onUpdate, this, std::placeholders::_1));
mWeb.on("/update", HTTP_POST, std::bind(&Web::showUpdate, this, std::placeholders::_1),
std::bind(&Web::showUpdate2, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5, std::placeholders::_6));
mWeb->on("/serial", HTTP_GET, std::bind(&Web::onSerial, this, std::placeholders::_1));
mWeb.on("/serial", HTTP_GET, std::bind(&Web::onSerial, this, std::placeholders::_1));
mEvts->onConnect(std::bind(&Web::onConnect, this, std::placeholders::_1));
mWeb->addHandler(mEvts);
mEvts.onConnect(std::bind(&Web::onConnect, this, std::placeholders::_1));
mWeb.addHandler(&mEvts);
registerDebugCb(std::bind(&Web::serialCb, this, std::placeholders::_1)); // dbg.h
}
mWeb.begin();
void loop(void) {
if(ah::checkTicker(&mWebSerialTicker, mWebSerialInterval)) {
if(mSerialBufFill > 0) {
mEvts->send(mSerialBuf, "serial", millis());
memset(mSerialBuf, 0, WEB_SERIAL_BUF_SIZE);
mSerialBufFill = 0;
}
}
registerDebugCb(std::bind(&Web::serialCb, this, std::placeholders::_1)); // dbg.h
}
void tickSecond() {
@ -117,10 +104,18 @@ class Web {
DPRINTLN(DBG_DEBUG, "auto logout in " + String(mLogoutTimeout));
}
if(mSerialClientConnnected) {
if(mSerialBufFill > 0) {
mEvts.send(mSerialBuf, "serial", millis());
memset(mSerialBuf, 0, WEB_SERIAL_BUF_SIZE);
mSerialBufFill = 0;
}
}
}
AsyncWebServer *getWebSrvPtr(void) {
return mWeb;
return &mWeb;
}
void setProtection(bool protect) {
@ -151,6 +146,9 @@ class Web {
}
void serialCb(String msg) {
if(!mSerialClientConnnected)
return;
msg.replace("\r\n", "<rn>");
if(mSerialAddTime) {
if((9 + mSerialBufFill) <= WEB_SERIAL_BUF_SIZE) {
@ -159,7 +157,7 @@ class Web {
}
else {
mSerialBufFill = 0;
mEvts->send("webSerial, buffer overflow!", "serial", millis());
mEvts.send("webSerial, buffer overflow!", "serial", millis());
}
mSerialAddTime = false;
}
@ -174,7 +172,7 @@ class Web {
}
else {
mSerialBufFill = 0;
mEvts->send("webSerial, buffer overflow!", "serial", millis());
mEvts.send("webSerial, buffer overflow!", "serial", millis());
}
}
@ -212,6 +210,8 @@ class Web {
void onConnect(AsyncEventSourceClient *client) {
DPRINTLN(DBG_VERBOSE, "onConnect");
mSerialClientConnnected = true;
if(client->lastId())
DPRINTLN(DBG_VERBOSE, "Client reconnected! Last message ID that it got is: " + String(client->lastId()));
@ -262,6 +262,7 @@ class Web {
}
void onCss(AsyncWebServerRequest *request) {
DPRINTLN(DBG_VERBOSE, F("onCss"));
mLogoutTimeout = LOGOUT_TIMEOUT;
AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/css"), style_css, style_css_len);
response->addHeader(F("Content-Encoding"), "gzip");
@ -373,7 +374,9 @@ class Web {
return;
}
if(request->args() > 0) {
if(request->args() == 0)
return;
char buf[20] = {0};
// general
@ -504,7 +507,6 @@ class Web {
request->send(response);
}
}
}
void onLive(AsyncWebServerRequest *request) {
DPRINTLN(DBG_VERBOSE, F("onLive"));
@ -632,7 +634,7 @@ class Web {
}
modJson += F("\"json_ts\": \"") + String(ah::getDateTimeStr(mMain->mTimestamp)) + F("\"\n}\n");
mWeb->send(200, F("application/json"), modJson);
mWeb.send(200, F("application/json"), modJson);
}
#endif
@ -663,7 +665,7 @@ class Web {
}
}
mWeb->send(200, F("text/plain"), metrics);
mWeb.send(200, F("text/plain"), metrics);
}
std::pair<String, String> convertToPromUnits(String shortUnit) {
@ -679,8 +681,8 @@ class Web {
}
#endif
AsyncWebServer *mWeb;
AsyncEventSource *mEvts;
AsyncWebServer mWeb;
AsyncEventSource mEvts;
bool mProtected;
uint32_t mLogoutTimeout;
IApp *mApp;
@ -691,8 +693,7 @@ class Web {
bool mSerialAddTime;
char mSerialBuf[WEB_SERIAL_BUF_SIZE];
uint16_t mSerialBufFill;
uint32_t mWebSerialTicker;
uint32_t mWebSerialInterval;
bool mSerialClientConnnected;
};
#endif /*__WEB_H__*/

101
src/wifi/ahoywifi.cpp

@ -12,34 +12,32 @@
// NTP CONFIG
#define NTP_PACKET_SIZE 48
enum {WIFI_NOT_FOUND = 0, WIFI_FOUND, WIFI_NOT_COMPLETE};
//-----------------------------------------------------------------------------
ahoywifi::ahoywifi() {
mCnt = 0;
mConnected = false;
mReconnect = false;
ahoywifi::ahoywifi() : mApIp(192, 168, 4, 1), mApMask(255, 255, 255, 0) {
mDnsActive = false;
mClientCnt = 0;
mLoopCnt = 250;
mExtScan = false;
}
//-----------------------------------------------------------------------------
void ahoywifi::setup(settings_t *config, uint32_t *utcTimestamp) {
mCnt = 0;
mConnected = false;
mReconnect = false;
mConfig = config;
mUtcTimestamp = utcTimestamp;
if(String(mConfig->sys.deviceName) != "")
WiFi.hostname(mConfig->sys.deviceName);
#if !defined(FB_WIFI_OVERRIDDEN)
if(strncmp(mConfig->sys.stationSsid, FB_WIFI_SSID, 14) == 0)
setupAp();
#endif
#if !defined(AP_ONLY)
if(mConfig->valid) {
#if !defined(FB_WIFI_OVERRIDDEN)
if(strncmp(mConfig->sys.stationSsid, FB_WIFI_SSID, 14) != 0)
setupStation();
#else
setupStation();
#endif
}
#endif
#if defined(ESP8266)
wifiConnectHandler = WiFi.onStationModeGotIP(std::bind(&ahoywifi::onConnect, this, std::placeholders::_1));
@ -59,19 +57,43 @@ void ahoywifi::loop() {
if((mCnt % 50) == 0)
WiFi.disconnect();
else if((mCnt % 60) == 0) {
WiFi.reconnect();
DPRINTLN(DBG_INFO, F("[WiFi] reconnect"));
WiFi.begin(mConfig->sys.stationSsid, mConfig->sys.stationPwd);
mCnt = 0;
}
}
#endif
yield();
if(mDnsActive) {
mDns.processNextRequest();
uint8_t cnt = WiFi.softAPgetStationNum();
if(cnt != mClientCnt) {
mClientCnt = cnt;
DPRINTLN(DBG_INFO, String(cnt) + F(" client(s) connected"));
}
if(!mExtScan && (mLoopCnt == 240)) {
if(scanStationNetwork()) {
setupStation();
mLoopCnt = 0;
}
}
if(0 != mLoopCnt) {
if(++mLoopCnt > 250) {
mLoopCnt = 1;
if(!mExtScan)
scanAvailNetworks(false);
}
delay(25);
}
}
#endif
}
//-----------------------------------------------------------------------------
void ahoywifi::setupAp(void) {
DPRINTLN(DBG_VERBOSE, F("wifi::setupAp"));
IPAddress apIp(192, 168, 4, 1);
DPRINTLN(DBG_INFO, F("wifi::setupAp"));
DBGPRINTLN(F("\n---------\nAhoyDTU Info:"));
DBGPRINT(F("Version: "));
@ -83,20 +105,22 @@ void ahoywifi::setupAp(void) {
DBGPRINTLN(WIFI_AP_SSID);
DBGPRINT(F("PWD: "));
DBGPRINTLN(WIFI_AP_PWD);
DBGPRINTLN("IP Address: http://" + apIp.toString());
DBGPRINTLN("IP Address: http://" + mApIp.toString());
DBGPRINTLN(F("---------\n"));
WiFi.mode(WIFI_AP_STA);
WiFi.softAPConfig(apIp, apIp, IPAddress(255, 255, 255, 0));
WiFi.softAPConfig(mApIp, mApIp, mApMask);
WiFi.softAP(WIFI_AP_SSID, WIFI_AP_PWD);
mDns.start(53, "*", apIp);
mDns.setErrorReplyCode(DNSReplyCode::NoError);
mDns.start(53, "*", WiFi.softAPIP());
mDnsActive = true;
}
//-----------------------------------------------------------------------------
void ahoywifi::setupStation(void) {
DPRINTLN(DBG_VERBOSE, F("wifi::setupStation"));
DPRINTLN(DBG_INFO, F("wifi::setupStation"));
if(mConfig->sys.ip.ip[0] != 0) {
IPAddress ip(mConfig->sys.ip.ip);
IPAddress mask(mConfig->sys.ip.mask);
@ -107,12 +131,27 @@ void ahoywifi::setupStation(void) {
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);
DBGPRINT(F("connect to network '"));
DBGPRINT(mConfig->sys.stationSsid);
DBGPRINTLN(F("' ..."));
}
//-----------------------------------------------------------------------------
bool ahoywifi::scanStationNetwork(void) {
bool found = false;
int n = WiFi.scanComplete();
if(n > 0) {
for (int i = 0; i < n; i++) {
DPRINTLN(DBG_INFO, "found network: " + WiFi.SSID(i));
if(String(mConfig->sys.stationSsid) == WiFi.SSID(i)) {
found = true;
break;
}
}
WiFi.scanDelete();
}
return found;
}
@ -156,9 +195,10 @@ bool ahoywifi::getNtpTime(void) {
//-----------------------------------------------------------------------------
void ahoywifi::scanAvailNetworks(void) {
int n = WiFi.scanComplete();
if(n == -2)
void ahoywifi::scanAvailNetworks(bool externalCall) {
if(externalCall)
mExtScan = true;
if(-2 == WiFi.scanComplete())
WiFi.scanNetworks(true);
}
@ -182,6 +222,7 @@ void ahoywifi::getAvailNetworks(JsonObject obj) {
}
WiFi.scanDelete();
}
mExtScan = false;
}
@ -215,6 +256,7 @@ void ahoywifi::sendNTPpacket(IPAddress& address) {
DBGPRINTLN(F("\n[WiFi] Connected"));
WiFi.mode(WIFI_STA);
DBGPRINTLN(F("[WiFi] AP disabled"));
mDnsActive = false;
mDns.stop();
welcome(WiFi.localIP().toString() + F(" (Station)"));
@ -245,6 +287,7 @@ void ahoywifi::sendNTPpacket(IPAddress& address) {
WiFi.mode(WIFI_STA);
WiFi.begin();
DBGPRINTLN(F("[WiFi] AP disabled"));
mDnsActive = false;
mDns.stop();
mReconnect = false;
}

12
src/wifi/ahoywifi.h

@ -23,12 +23,13 @@ class ahoywifi {
void setup(settings_t *config, uint32_t *utcTimestamp);
void loop(void);
bool getNtpTime(void);
void scanAvailNetworks(void);
void scanAvailNetworks(bool externalCall = true);
void getAvailNetworks(JsonObject obj);
private:
void setupAp(void);
void setupStation(void);
bool scanStationNetwork(void);
void sendNTPpacket(IPAddress& address);
#if defined(ESP8266)
void onConnect(const WiFiEventStationModeGotIP& event);
@ -38,18 +39,23 @@ class ahoywifi {
#endif
void welcome(String msg);
settings_t *mConfig;
DNSServer mDns;
IPAddress mApIp, mApMask;
WiFiUDP mUdp; // for time server
#if defined(ESP8266)
WiFiEventHandler wifiConnectHandler;
WiFiEventHandler wifiDisconnectHandler;
#endif
bool mConnected, mReconnect;
uint8_t mCnt;
bool mConnected, mReconnect, mDnsActive;
uint8_t mCnt, mClientCnt;
uint32_t *mUtcTimestamp;
uint8_t mLoopCnt;
bool mExtScan;
};
#endif /*__AHOYWIFI_H__*/

Loading…
Cancel
Save