Browse Source

fix #480 AP Mode on fresh ESP

included #483 improvements
fix #468 last_success MQTT
fix #468 update available status at sunset
fix #447 reorderd enqueue commands to not have same payload length in a row
added ssd1306 and nokia display to build script
pull/487/head
lumapu 2 years ago
parent
commit
d9290d9fdf
  1. 2
      .github/workflows/compile_development.yml
  2. 2
      .github/workflows/compile_esp8266.yml
  3. 53
      src/app.cpp
  4. 2
      src/app.h
  5. 8
      src/config/settings.h
  6. 2
      src/defines.h
  7. 9
      src/hm/hmInverter.h
  8. 2
      src/main.cpp
  9. 3
      src/publisher/pubMqtt.h
  10. 37
      src/publisher/pubSerial.h
  11. 108
      src/utils/llist.h
  12. 238
      src/utils/scheduler.h
  13. 2
      src/utils/sun.h
  14. 14
      src/web/html/index.html
  15. 9
      src/wifi/ahoywifi.cpp

2
.github/workflows/compile_development.yml

@ -47,7 +47,7 @@ jobs:
run: python convert.py
- name: Run PlatformIO
run: pio run -d src --environment esp8266-release --environment esp8285-release --environment esp32-wroom32-release
run: pio run -d src --environment esp8266-release --environment esp8285-release --environment esp8266-nokia5110 --environment esp8266-ssd1306 --environment esp32-wroom32-release
- name: Rename Binary files
id: rename-binary-files

2
.github/workflows/compile_esp8266.yml

@ -49,7 +49,7 @@ jobs:
working-directory: src/web/html
run: python convert.py
- name: Run PlatformIO
run: pio run -d tools/esp8266 --environment esp8266-release --environment esp8285-release --environment esp32-wroom32-release
run: pio run -d tools/esp8266 --environment esp8266-release --environment esp8285-release --environment esp8266-nokia5110 --environment esp8266-ssd1306 --environment esp32-wroom32-release
- name: Rename Binary files
id: rename-binary-files

53
src/app.cpp

@ -19,24 +19,29 @@ app::app() : ah::Scheduler() {
//-----------------------------------------------------------------------------
void app::setup(uint32_t timeout) {
void app::setup() {
Serial.begin(115200);
while (!Serial)
yield();
ah::Scheduler::setup();
resetSystem();
mSettings.setup();
mSettings.getPtr(mConfig);
DPRINTLN(DBG_INFO, F("Settings valid: ") + String((mSettings.getValid()) ? F("true") : F("false")));
addListener(EVERY_SEC, std::bind(&app::tickSecond, this));
addListener(EVERY_MIN, std::bind(&app::tickMinute, this));
addListener(EVERY_12H, std::bind(&app::tickNtpUpdate, this));
once(mConfig->nrf.sendInterval, std::bind(&app::tickSend, this), "tickSend");
if((mConfig->sun.lat) && (mConfig->sun.lon)) {
once(5, std::bind(&app::tickCalcSunrise, this));
mCalculatedTimezoneOffset = (int8_t)((mConfig->sun.lon >= 0 ? mConfig->sun.lon + 7.5 : mConfig->sun.lon - 7.5) / 15) * 3600;
}
everySec(std::bind(&app::tickSecond, this));
everyMin(std::bind(&app::tickMinute, this));
every12h(std::bind(&app::tickNtpUpdate, this));
every(std::bind(&app::tickSend, this), mConfig->nrf.sendInterval);
#if !defined(AP_ONLY)
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
mSys = new HmSystemType();
mSys->enableDebug();
@ -54,10 +59,9 @@ void app::setup(uint32_t timeout) {
#if !defined(AP_ONLY)
if (mConfig->mqtt.broker[0] > 0) {
mPayload.addListener(std::bind(&PubMqttType::payloadEventListener, &mMqtt, std::placeholders::_1));
addListener(EVERY_SEC, std::bind(&PubMqttType::tickerSecond, &mMqtt));
addListener(EVERY_MIN, std::bind(&PubMqttType::tickerMinute, &mMqtt));
everySec(std::bind(&PubMqttType::tickerSecond, &mMqtt));
everyMin(std::bind(&PubMqttType::tickerMinute, &mMqtt));
mMqtt.setSubscriptionCb(std::bind(&app::mqttSubRxCb, this, std::placeholders::_1));
}
#endif
setupLed();
@ -65,16 +69,17 @@ void app::setup(uint32_t timeout) {
mWeb = new web(this, mConfig, &mStat, mVersion);
mWeb->setup();
mWeb->setProtection(strlen(mConfig->sys.adminPwd) != 0);
addListener(EVERY_SEC, std::bind(&web::tickSecond, mWeb));
everySec(std::bind(&web::tickSecond, mWeb));
// Plugins
#if defined(ENA_NOKIA) || defined(ENA_SSD1306)
mMonoDisplay.setup(mSys, &mTimestamp);
mPayload.addListener(std::bind(&MonoDisplayType::payloadEventListener, &mMonoDisplay, std::placeholders::_1));
addListener(EVERY_SEC, std::bind(&MonoDisplayType::tickerSecond, &mMonoDisplay));
everySec(std::bind(&MonoDisplayType::tickerSecond, &mMonoDisplay));
#endif
//addListener(EVERY_MIN, std::bind(&PubSerialType::tickerMinute, &mPubSerial));
mPubSerial.setup(mConfig, mSys, &mTimestamp);
every(std::bind(&PubSerialType::tick, &mPubSerial), mConfig->serial.interval);
}
//-----------------------------------------------------------------------------
@ -129,27 +134,26 @@ void app::loop(void) {
//-----------------------------------------------------------------------------
void app::tickCalcSunrise(void) {
if (0 == mTimestamp) {
once(5, std::bind(&app::tickCalcSunrise, this)); // check again in 5 secs
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);
uint32_t nxtTrig = mTimestamp - (mTimestamp % 86400) + 86400; // next midnight
onceAt(nxtTrig, std::bind(&app::tickCalcSunrise, this), "calc sunrise");
onceAt(mSunrise, std::bind(&app::tickSend, this), "tickSend"); // register next event
onceAt(std::bind(&app::tickCalcSunrise, this), nxtTrig);
if (mConfig->mqtt.broker[0] > 0) {
once(1, std::bind(&PubMqttType::tickerSun, &mMqtt), "MQTT-tickerSun");
onceAt(mSunset, std::bind(&PubMqttType::tickSunset, &mMqtt));
once(std::bind(&PubMqttType::tickerSun, &mMqtt), 1);
onceAt(std::bind(&PubMqttType::tickSunset, &mMqtt), mSunset);
}
}
//-----------------------------------------------------------------------------
void app::tickSend(void) {
if(!mSys->Radio.isChipConnected()) {
DPRINTLN(DBG_WARN, "NRF24 not connected!");
return;
}
if ((mTimestamp > 0) && (!mConfig->sun.disNightCom || (mTimestamp >= mSunrise && mTimestamp <= mSunset))) { // Timestamp is set and (inverter communication only during the day if the option is activated and sunrise/sunset is set)
once(mConfig->nrf.sendInterval, std::bind(&app::tickSend, this), "tickSend"); // register next event
if (mConfig->serial.debug)
DPRINTLN(DBG_DEBUG, F("Free heap: 0x") + String(ESP.getFreeHeap(), HEX));
if (!mSys->BufCtrl.empty()) {
if (mConfig->serial.debug)
DPRINTLN(DBG_DEBUG, F("recbuf not empty! #") + String(mSys->BufCtrl.getFill()));
@ -206,7 +210,6 @@ void app::tickSend(void) {
}
}
} else {
once(3600, std::bind(&app::tickSend, this), "tickSend"); // register next event (one hour)
if (mConfig->serial.debug)
DPRINTLN(DBG_WARN, F("Time not set or it is night time, therefore no communication to the inverter!"));
}

2
src/app.h

@ -52,7 +52,7 @@ class app : public ah::Scheduler {
app();
~app() {}
void setup(uint32_t timeout);
void setup(void);
void loop(void);
void handleIntr(void);
void cbMqtt(char* topic, byte* payload, unsigned int length);

8
src/config/settings.h

@ -98,6 +98,7 @@ typedef struct {
cfgMqtt_t mqtt;
cfgLed_t led;
cfgInst_t inst;
bool valid;
} settings_t;
class settings {
@ -107,7 +108,7 @@ class settings {
void setup() {
DPRINTLN(DBG_INFO, F("Initializing FS .."));
mValid = false;
mCfg.valid = false;
#if !defined(ESP32)
LittleFSConfig cfg;
cfg.setAutoFormat(false);
@ -145,7 +146,7 @@ class settings {
}
bool getValid(void) {
return mValid;
return mCfg.valid;
}
void getInfo(uint32_t *used, uint32_t *size) {
@ -173,7 +174,7 @@ class settings {
DynamicJsonDocument root(4096);
DeserializationError err = deserializeJson(root, fp);
if(!err) {
mValid = true;
mCfg.valid = true;
jsonWifi(root["wifi"]);
jsonNrf(root["nrf"]);
jsonNtp(root["ntp"]);
@ -409,7 +410,6 @@ class settings {
}
settings_t mCfg;
bool mValid;
};
#endif /*__SETTINGS_H__*/

2
src/defines.h

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

9
src/hm/hmInverter.h

@ -160,17 +160,12 @@ class Inverter {
}
uint8_t getQueuedCmd() {
if (_commandQueue.empty()){
// Fill with default commands
enqueCommand<InfoCommand>(RealTimeRunData_Debug);
if (_commandQueue.empty()) {
if (fwVersion == 0)
{ // info needed maybe after "one night" (=> DC>0 to DC=0 and to DC>0) or reboot
enqueCommand<InfoCommand>(InverterDevInform_All);
}
enqueCommand<InfoCommand>(RealTimeRunData_Debug);
if (actPowerLimit == 0xffff)
{ // info needed maybe after "one nigth" (=> DC>0 to DC=0 and to DC>0) or reboot
enqueCommand<InfoCommand>(SystemConfigPara);
}
}
return _commandQueue.front().get()->getCmd();
}

2
src/main.cpp

@ -18,7 +18,7 @@ IRAM_ATTR void handleIntr(void) {
//-----------------------------------------------------------------------------
void setup() {
myApp.setup(WIFI_TRY_CONNECT_TIME);
myApp.setup();
// TODO: move to HmRadio
attachInterrupt(digitalPinToInterrupt(myApp.getIrqPin()), handleIntr, FALLING);

3
src/publisher/pubMqtt.h

@ -95,6 +95,7 @@ class PubMqtt {
}
void tickSunset() {
printf("tickSunset\n");
char topic[MAX_NAME_LENGTH + 15], val[32];
for (uint8_t id = 0; id < mSys->getNumInverters(); id++) {
Inverter<> *iv = mSys->getInverterByPos(id);
@ -387,7 +388,7 @@ class PubMqtt {
publish(topic, val, true);
snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/last_success", iv->config->name);
snprintf(val, 40, "%i", iv->getLastTs(rec) * 1000);
snprintf(val, 40, "%d", iv->getLastTs(rec));
publish(topic, val, true);
}

37
src/publisher/pubSerial.h

@ -21,28 +21,24 @@ class PubSerial {
mUtcTimestamp = utcTs;
}
void tickerMinute() {
DPRINTLN(DBG_INFO, "tickerMinute");
if(++mTick >= mCfg->serial.interval) {
mTick = 0;
if (mCfg->serial.showIv) {
char topic[30], val[10];
for (uint8_t id = 0; id < mSys->getNumInverters(); id++) {
Inverter<> *iv = mSys->getInverterByPos(id);
if (NULL != iv) {
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug);
if (iv->isAvailable(*mUtcTimestamp, rec)) {
DPRINTLN(DBG_INFO, F("Inverter: ") + String(id));
for (uint8_t i = 0; i < rec->length; i++) {
if (0.0f != iv->getValue(i, rec)) {
snprintf(topic, 30, "%s/ch%d/%s", iv->config->name, rec->assign[i].ch, iv->getFieldName(i, rec));
snprintf(val, 10, "%.3f %s", iv->getValue(i, rec), iv->getUnit(i, rec));
DPRINTLN(DBG_INFO, String(topic) + ": " + String(val));
}
yield();
void tick(void) {
if (mCfg->serial.showIv) {
char topic[32 + MAX_NAME_LENGTH], val[40];
for (uint8_t id = 0; id < mSys->getNumInverters(); id++) {
Inverter<> *iv = mSys->getInverterByPos(id);
if (NULL != iv) {
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug);
if (iv->isAvailable(*mUtcTimestamp, rec)) {
DPRINTLN(DBG_INFO, F("Inverter: ") + String(id));
for (uint8_t i = 0; i < rec->length; i++) {
if (0.0f != iv->getValue(i, rec)) {
snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/ch%d/%s", iv->config->name, rec->assign[i].ch, iv->getFieldName(i, rec));
snprintf(val, 40, "%.3f %s", iv->getValue(i, rec), iv->getUnit(i, rec));
DPRINTLN(DBG_INFO, String(topic) + ": " + String(val));
}
DPRINTLN(DBG_INFO, "");
yield();
}
DPRINTLN(DBG_INFO, "");
}
}
}
@ -52,7 +48,6 @@ class PubSerial {
private:
settings_t *mCfg;
HMSYSTEM *mSys;
uint8_t mTick;
uint32_t *mUtcTimestamp;
};

108
src/utils/llist.h

@ -0,0 +1,108 @@
//-----------------------------------------------------------------------------
// 2022 Ahoy, https://ahoydtu.de
// Lukas Pusch, lukas@lpusch.de
// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/
//-----------------------------------------------------------------------------
#ifndef __LIST_H__
#define __LIST_H__
template<class T, class... Args>
struct node_s {
typedef T dT;
node_s *pre;
node_s *nxt;
uint32_t id;
dT d;
node_s() : pre(NULL), nxt(NULL), d() {}
node_s(Args... args) : id(0), pre(NULL), nxt(NULL), d(args...) {}
};
template<int MAX_NUM, class T, class... Args>
class llist {
typedef node_s<T, Args...> elmType;
typedef T dataType;
public:
llist() : root(mPool) {
root = NULL;
elmType *p = mPool;
for(uint32_t i = 0; i < MAX_NUM; i++) {
p->id = i;
p++;
}
mFill = mMax = 0;
}
elmType *add(Args... args) {
elmType *p = root, *t;
if(NULL == (t = getFreeNode()))
return NULL;
if(++mFill > mMax)
mMax = mFill;
if(NULL == root) {
p = root = t;
p->pre = p;
p->nxt = p;
}
else {
p = root->pre;
t->pre = p;
p->nxt->pre = t;
t->nxt = p->nxt;
p->nxt = t;
}
t->d = dataType(args...);
return p;
}
elmType *getFront() {
return root;
}
elmType *get(elmType *p) {
p = p->nxt;
return (p == root) ? NULL : p;
}
elmType *rem(elmType *p) {
if(NULL == p)
return NULL;
elmType *t = p->nxt;
p->nxt->pre = p->pre;
p->pre->nxt = p->nxt;
if(root == p)
root = NULL;
p->nxt = NULL;
p->pre = NULL;
p = NULL;
mFill--;
return (NULL == root) ? NULL : ((t == root) ? NULL : t);
}
uint16_t getFill(void) {
return mFill;
}
uint16_t getMaxFill(void) {
return mMax;
}
protected:
elmType *root;
private:
elmType *getFreeNode(void) {
elmType *n = mPool;
for(uint32_t i = 0; i < MAX_NUM; i++) {
if(NULL == n->nxt)
return n;
n++;
}
return NULL;
}
elmType mPool[MAX_NUM];
uint16_t mFill, mMax;
};
#endif /*__LIST_H__*/

238
src/utils/scheduler.h

@ -7,152 +7,132 @@
#ifndef __SCHEDULER_H__
#define __SCHEDULER_H__
#include <memory>
#include <functional>
#include <list>
enum {EVERY_SEC = 1, EVERY_MIN, EVERY_HR, EVERY_12H, EVERY_DAY};
typedef std::function<void()> SchedulerCb;
struct once_t {
uint32_t n;
SchedulerCb f;
once_t(uint32_t a, SchedulerCb b) : n(a), f(b) {}
once_t() : n(0), f(NULL) {}
};
#include "llist.h"
#include "dbg.h"
namespace ah {
class Scheduler {
public:
Scheduler() {}
void setup() {
mPrevMillis = 0;
mSeconds = 0;
mMinutes = 0;
mHours = 0;
mUptime = 0;
mTimestamp = 0;
}
void loop() {
if (millis() - mPrevMillis >= 1000) {
mPrevMillis += 1000;
mUptime++;
if(0 != mTimestamp)
mTimestamp++;
notify(&mListSecond);
onceFuncTick();
if(++mSeconds >= 60) {
mSeconds = 0;
notify(&mListMinute);
onceAtFuncTick();
if(++mMinutes >= 60) {
mMinutes = 0;
notify(&mListHour);
if(++mHours >= 24) {
mHours = 0;
notify(&mListDay);
notify(&mList12h);
}
else if(mHours == 12)
notify(&mList12h);
}
}
typedef std::function<void()> scdCb;
enum {SCD_SEC = 1, SCD_MIN = 60, SCD_HOUR = 3600, SCD_12H = 43200, SCD_DAY = 86400};
struct scdEvry_s {
scdCb c;
uint32_t timeout;
uint32_t reload;
scdEvry_s() : c(NULL), timeout(0), reload(0) {}
scdEvry_s(scdCb a, uint32_t tmt, uint32_t rl) : c(a), timeout(tmt), reload(rl) {}
};
struct scdAt_s {
scdCb c;
uint32_t timestamp;
scdAt_s() : c(NULL), timestamp(0) {}
scdAt_s(scdCb a, uint32_t ts) : c(a), timestamp(ts) {}
};
typedef node_s<scdEvry_s, scdCb, uint32_t, uint32_t> sP;
typedef node_s<scdAt_s, scdCb, uint32_t> sPAt;
class Scheduler {
public:
Scheduler() {}
void setup() {
mUptime = 0;
mTimestamp = 0;
mPrevMillis = millis();
}
}
// checked every second
void once(uint32_t sec, SchedulerCb cb, const char *info = NULL) {
if(NULL != info) {
DPRINT(DBG_INFO, F("once in [s]: ") + String(sec));
DBGPRINTLN(F(", ") + String(info));
}
mOnce.push_back(once_t(sec, cb));
}
// checked every minute
void onceAt(uint32_t timestamp, SchedulerCb cb, const char *info = NULL) {
if(timestamp > mTimestamp) {
if(NULL != info) {
DPRINT(DBG_INFO, F("onceAt (UTC): ") + getDateTimeStr(timestamp));
DBGPRINTLN(F(", ") + String(info));
void loop(void) {
mMillis = millis();
mDiff = mMillis - mPrevMillis;
if(mDiff >= 1000) {
if(mMillis < mPrevMillis) { // overflow
mPrevMillis = mMillis;
return;
}
mDiffSeconds = mDiff / 1000;
mPrevMillis += (mPrevMillis * 1000);
checkEvery();
checkAt();
mUptime += mDiffSeconds;
if(0 != mTimestamp)
mTimestamp += mDiffSeconds;
}
mOnceAt.push_back(once_t(timestamp, cb));
}
}
virtual void setTimestamp(uint32_t ts) {
mTimestamp = ts;
}
void addListener(uint8_t every, SchedulerCb cb) {
switch(every) {
case EVERY_SEC: mListSecond.push_back(cb); break;
case EVERY_MIN: mListMinute.push_back(cb); break;
case EVERY_HR: mListHour.push_back(cb); break;
case EVERY_12H: mList12h.push_back(cb); break;
case EVERY_DAY: mListDay.push_back(cb); break;
default: break;
void once(scdCb c, uint32_t timeout) { mStack.add(c, timeout, 0); }
void every(scdCb c, uint32_t interval) { mStack.add(c, interval, interval); }
void onceAt(scdCb c, uint32_t timestamp) { mStackAt.add(c, timestamp); }
void everySec(scdCb c) { mStack.add(c, SCD_SEC, SCD_SEC); }
void everyMin(scdCb c) { mStack.add(c, SCD_MIN, SCD_MIN); }
void everyHour(scdCb c) { mStack.add(c, SCD_HOUR, SCD_HOUR); }
void every12h(scdCb c) { mStack.add(c, SCD_12H, SCD_12H); }
void everyDay(scdCb c) { mStack.add(c, SCD_DAY, SCD_DAY); }
virtual void setTimestamp(uint32_t ts) {
mTimestamp = ts;
}
}
uint32_t getUptime(void) {
return mUptime;
}
uint32_t getUptime(void) {
return mUptime;
}
uint32_t getTimestamp(void) {
return mTimestamp;
}
uint32_t getTimestamp(void) {
return mTimestamp;
}
protected:
virtual void notify(std::list<SchedulerCb> *lType) {
for(std::list<SchedulerCb>::iterator it = lType->begin(); it != lType->end(); ++it) {
(*it)();
void stat() {
DPRINTLN(DBG_INFO, "max fill every: " + String(mStack.getMaxFill()));
DPRINTLN(DBG_INFO, "max fill at: " + String(mStackAt.getMaxFill()));
}
}
uint32_t mTimestamp;
private:
void onceFuncTick(void) {
if(mOnce.empty())
return;
for(std::list<once_t>::iterator it = mOnce.begin(); it != mOnce.end();) {
if(((*it).n)-- == 0) {
((*it).f)();
it = mOnce.erase(it);
protected:
uint32_t mTimestamp;
private:
inline void checkEvery(void) {
bool expired;
sP *p = mStack.getFront();
while(NULL != p) {
if(mDiffSeconds >= p->d.timeout) expired = true;
else if((p->d.timeout--) == 0) expired = true;
else expired = false;
if(expired) {
(p->d.c)();
if(0 == p->d.reload)
p = mStack.rem(p);
else {
p->d.timeout = p->d.reload - 1;
p = mStack.get(p);
}
}
else
p = mStack.get(p);
}
else
++it;
}
}
void onceAtFuncTick(void) {
if(mOnceAt.empty())
return;
for(std::list<once_t>::iterator it = mOnceAt.begin(); it != mOnceAt.end();) {
if(((*it).n) < mTimestamp) {
((*it).f)();
it = mOnceAt.erase(it);
inline void checkAt(void) {
sPAt *p = mStackAt.getFront();
while(NULL != p) {
if((p->d.timestamp) <= mTimestamp) {
(p->d.c)();
p = mStackAt.rem(p);
}
else
p = mStackAt.get(p);
}
else
++it;
}
}
std::list<SchedulerCb> mListSecond;
std::list<SchedulerCb> mListMinute;
std::list<SchedulerCb> mListHour;
std::list<SchedulerCb> mList12h;
std::list<SchedulerCb> mListDay;
std::list<once_t> mOnce;
std::list<once_t> mOnceAt;
uint32_t mPrevMillis, mUptime;
uint8_t mSeconds, mMinutes, mHours;
};
llist<25, scdEvry_s, scdCb, uint32_t, uint32_t> mStack;
llist<10, scdAt_s, scdCb, uint32_t> mStackAt;
uint32_t mMillis, mPrevMillis, mDiff;
uint32_t mUptime;
uint8_t mDiffSeconds;
};
}
#endif /*__SCHEDULER_H__*/

2
src/utils/sun.h

@ -10,7 +10,7 @@ namespace ah {
void calculateSunriseSunset(uint32_t utcTs, uint32_t offset, float lat, float lon, uint32_t *sunrise, uint32_t *sunset) {
// Source: https://en.wikipedia.org/wiki/Sunrise_equation#Complete_calculation_on_Earth
// Julian day since 1.1.2000 12:00 + correction 69.12s
// Julian day since 1.1.2000 12:00
double n_JulianDay = (utcTs + offset) / 86400 - 10957.0;
// Mean solar time
double J = n_JulianDay - lon / 360;

14
src/web/html/index.html

@ -48,9 +48,6 @@
<div id="note">
Discuss with us on <a href="https://discord.gg/WzhxEY62mB">Discord</a><br/>
<h3>Documentation</h3>
<a href="https://ahoydtu.de" target="_blank">ahoydtu.de</a>
<h3>Support this project:</h3>
<ul>
<li>Report <a href="https://github.com/lumapu/ahoy/issues" target="_blank">issues</a></li>
@ -118,10 +115,13 @@
var sec = up % 60;
var sunrise = new Date(obj["ts_sunrise"] * 1000);
var sunset = new Date(obj["ts_sunset"] * 1000);
document.getElementById("uptime").innerHTML = days + " Days, "
+ ("0"+hrs).substr(-2) + ":"
+ ("0"+min).substr(-2) + ":"
+ ("0"+sec).substr(-2);
var e = document.getElementById("uptime");
e.innerHTML = days + " Day";
if(1 != days)
e.innerHTML += "s";
e.innerHTML += ", " + ("0"+hrs).substr(-2) + ":"
+ ("0"+min).substr(-2) + ":"
+ ("0"+sec).substr(-2);
var dSpan = document.getElementById("date");
if(0 != obj["ts_now"])
dSpan.innerHTML = date.toLocaleString('de-DE');

9
src/wifi/ahoywifi.cpp

@ -8,8 +8,6 @@
#define F(sl) (sl)
#endif
#include "ahoywifi.h"
#include "../utils/ahoyTimer.h"
// NTP CONFIG
#define NTP_PACKET_SIZE 48
@ -25,17 +23,16 @@ ahoywifi::ahoywifi() {
//-----------------------------------------------------------------------------
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)
if(strncmp(mConfig->sys.stationSsid, FB_WIFI_SSID, 14) == 0)
setupAp();
#endif
#if !defined(AP_ONLY)
setupStation();
ah::ip2Char(mConfig->sys.ip.ip, ipSta);
if(mConfig->valid)
setupStation();
#endif
#if defined(ESP8266)

Loading…
Cancel
Save