mirror of
https://github.com/lumapu/ahoy.git
synced 2025-06-02 18:51:38 +02:00
0.8.115
* fix inverter communication with manual time sync #1603 * improved queue, only add new object once they not exist * added option to reset values on communication start (sunrise)
This commit is contained in:
parent
4fe5c8eef8
commit
84ac10531a
10 changed files with 60 additions and 18 deletions
|
@ -1,5 +1,10 @@
|
||||||
# Development Changes
|
# Development Changes
|
||||||
|
|
||||||
|
## 0.8.115 - 2024-05-03
|
||||||
|
* fix inverter communication with manual time sync #1603
|
||||||
|
* improved queue, only add new object once they not exist
|
||||||
|
* added option to reset values on communication start (sunrise)
|
||||||
|
|
||||||
## 0.8.114 - 2024-04-29
|
## 0.8.114 - 2024-04-29
|
||||||
* fix ESP8266 compile
|
* fix ESP8266 compile
|
||||||
* fix history graph
|
* fix history graph
|
||||||
|
|
|
@ -162,6 +162,9 @@ void app::regularTickers(void) {
|
||||||
everySec([this]() { mProtection->tickSecond(); }, "prot");
|
everySec([this]() { mProtection->tickSecond(); }, "prot");
|
||||||
everySec([this]() {mNetwork->tickNetworkLoop(); }, "net");
|
everySec([this]() {mNetwork->tickNetworkLoop(); }, "net");
|
||||||
|
|
||||||
|
if(mConfig->inst.startWithoutTime && !mNetworkConnected)
|
||||||
|
every(std::bind(&app::tickSend, this), mConfig->inst.sendInterval, "tSend");
|
||||||
|
|
||||||
// Plugins
|
// Plugins
|
||||||
#if defined(PLUGIN_DISPLAY)
|
#if defined(PLUGIN_DISPLAY)
|
||||||
if (DISP_TYPE_T0_NONE != mConfig->plugin.display.type)
|
if (DISP_TYPE_T0_NONE != mConfig->plugin.display.type)
|
||||||
|
@ -275,6 +278,8 @@ void app::tickIVCommunication(void) {
|
||||||
if (mTimestamp >= (mSunset + mConfig->sun.offsetSecEvening)) { // current time is past communication stop, nothing to do. Next update will be done at midnight by tickCalcSunrise
|
if (mTimestamp >= (mSunset + mConfig->sun.offsetSecEvening)) { // current time is past communication stop, nothing to do. Next update will be done at midnight by tickCalcSunrise
|
||||||
nxtTrig = 0;
|
nxtTrig = 0;
|
||||||
} else { // current time lies within communication start/stop time, set next trigger to communication stop
|
} else { // current time lies within communication start/stop time, set next trigger to communication stop
|
||||||
|
if((!iv->commEnabled) && mConfig->inst.rstValsCommStart)
|
||||||
|
zeroValues = true;
|
||||||
iv->commEnabled = true;
|
iv->commEnabled = true;
|
||||||
nxtTrig = mSunset + mConfig->sun.offsetSecEvening;
|
nxtTrig = mSunset + mConfig->sun.offsetSecEvening;
|
||||||
}
|
}
|
||||||
|
|
|
@ -303,8 +303,10 @@ class app : public IApp, public ah::Scheduler {
|
||||||
DBGPRINTLN(String(newTime));
|
DBGPRINTLN(String(newTime));
|
||||||
if(0 == newTime)
|
if(0 == newTime)
|
||||||
mNetwork->updateNtpTime();
|
mNetwork->updateNtpTime();
|
||||||
else
|
else {
|
||||||
Scheduler::setTimestamp(newTime);
|
Scheduler::setTimestamp(newTime);
|
||||||
|
onNtpUpdate(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t getHistoryValue(uint8_t type, uint16_t i) override {
|
uint16_t getHistoryValue(uint8_t type, uint16_t i) override {
|
||||||
|
|
|
@ -188,6 +188,7 @@ typedef struct {
|
||||||
bool rstYieldMidNight;
|
bool rstYieldMidNight;
|
||||||
bool rstValsNotAvail;
|
bool rstValsNotAvail;
|
||||||
bool rstValsCommStop;
|
bool rstValsCommStop;
|
||||||
|
bool rstValsCommStart;
|
||||||
bool rstMaxValsMidNight;
|
bool rstMaxValsMidNight;
|
||||||
bool startWithoutTime;
|
bool startWithoutTime;
|
||||||
bool readGrid;
|
bool readGrid;
|
||||||
|
@ -486,13 +487,14 @@ class settings {
|
||||||
mCfg.mqtt.interval = 0; // off
|
mCfg.mqtt.interval = 0; // off
|
||||||
mCfg.mqtt.enableRetain = true;
|
mCfg.mqtt.enableRetain = true;
|
||||||
|
|
||||||
mCfg.inst.sendInterval = SEND_INTERVAL;
|
mCfg.inst.sendInterval = SEND_INTERVAL;
|
||||||
mCfg.inst.rstYieldMidNight = false;
|
mCfg.inst.rstYieldMidNight = false;
|
||||||
mCfg.inst.rstValsNotAvail = false;
|
mCfg.inst.rstValsNotAvail = false;
|
||||||
mCfg.inst.rstValsCommStop = false;
|
mCfg.inst.rstValsCommStop = false;
|
||||||
mCfg.inst.startWithoutTime = false;
|
mCfg.inst.rstValsCommStart = false;
|
||||||
|
mCfg.inst.startWithoutTime = false;
|
||||||
mCfg.inst.rstMaxValsMidNight = false;
|
mCfg.inst.rstMaxValsMidNight = false;
|
||||||
mCfg.inst.readGrid = true;
|
mCfg.inst.readGrid = true;
|
||||||
|
|
||||||
for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) {
|
for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) {
|
||||||
mCfg.inst.iv[i].powerLevel = 0xff; // impossible high value
|
mCfg.inst.iv[i].powerLevel = 0xff; // impossible high value
|
||||||
|
@ -822,6 +824,7 @@ class settings {
|
||||||
obj[F("rstMidNight")] = (bool)mCfg.inst.rstYieldMidNight;
|
obj[F("rstMidNight")] = (bool)mCfg.inst.rstYieldMidNight;
|
||||||
obj[F("rstNotAvail")] = (bool)mCfg.inst.rstValsNotAvail;
|
obj[F("rstNotAvail")] = (bool)mCfg.inst.rstValsNotAvail;
|
||||||
obj[F("rstComStop")] = (bool)mCfg.inst.rstValsCommStop;
|
obj[F("rstComStop")] = (bool)mCfg.inst.rstValsCommStop;
|
||||||
|
obj[F("rstComStart")] = (bool)mCfg.inst.rstValsCommStart;
|
||||||
obj[F("strtWthtTime")] = (bool)mCfg.inst.startWithoutTime;
|
obj[F("strtWthtTime")] = (bool)mCfg.inst.startWithoutTime;
|
||||||
obj[F("rstMaxMidNight")] = (bool)mCfg.inst.rstMaxValsMidNight;
|
obj[F("rstMaxMidNight")] = (bool)mCfg.inst.rstMaxValsMidNight;
|
||||||
obj[F("rdGrid")] = (bool)mCfg.inst.readGrid;
|
obj[F("rdGrid")] = (bool)mCfg.inst.readGrid;
|
||||||
|
@ -832,6 +835,7 @@ class settings {
|
||||||
getVal<bool>(obj, F("rstMidNight"), &mCfg.inst.rstYieldMidNight);
|
getVal<bool>(obj, F("rstMidNight"), &mCfg.inst.rstYieldMidNight);
|
||||||
getVal<bool>(obj, F("rstNotAvail"), &mCfg.inst.rstValsNotAvail);
|
getVal<bool>(obj, F("rstNotAvail"), &mCfg.inst.rstValsNotAvail);
|
||||||
getVal<bool>(obj, F("rstComStop"), &mCfg.inst.rstValsCommStop);
|
getVal<bool>(obj, F("rstComStop"), &mCfg.inst.rstValsCommStop);
|
||||||
|
getVal<bool>(obj, F("rstComStart"), &mCfg.inst.rstValsCommStart);
|
||||||
getVal<bool>(obj, F("strtWthtTime"), &mCfg.inst.startWithoutTime);
|
getVal<bool>(obj, F("strtWthtTime"), &mCfg.inst.startWithoutTime);
|
||||||
getVal<bool>(obj, F("rstMaxMidNight"), &mCfg.inst.rstMaxValsMidNight);
|
getVal<bool>(obj, F("rstMaxMidNight"), &mCfg.inst.rstMaxValsMidNight);
|
||||||
getVal<bool>(obj, F("rdGrid"), &mCfg.inst.readGrid);
|
getVal<bool>(obj, F("rdGrid"), &mCfg.inst.readGrid);
|
||||||
|
|
|
@ -19,13 +19,19 @@ template <uint8_t N=100>
|
||||||
class CommQueue {
|
class CommQueue {
|
||||||
public:
|
public:
|
||||||
void addImportant(Inverter<> *iv, uint8_t cmd) {
|
void addImportant(Inverter<> *iv, uint8_t cmd) {
|
||||||
dec(&mRdPtr);
|
queue_s q(iv, cmd, true);
|
||||||
mQueue[mRdPtr] = queue_s(iv, cmd, true);
|
if(!isIncluded(&q)) {
|
||||||
|
dec(&mRdPtr);
|
||||||
|
mQueue[mRdPtr] = q;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void add(Inverter<> *iv, uint8_t cmd) {
|
void add(Inverter<> *iv, uint8_t cmd) {
|
||||||
mQueue[mWrPtr] = queue_s(iv, cmd, false);
|
queue_s q(iv, cmd, false);
|
||||||
inc(&mWrPtr);
|
if(!isIncluded(&q)) {
|
||||||
|
mQueue[mWrPtr] = q;
|
||||||
|
inc(&mWrPtr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void chgCmd(Inverter<> *iv, uint8_t cmd) {
|
void chgCmd(Inverter<> *iv, uint8_t cmd) {
|
||||||
|
@ -117,6 +123,19 @@ class CommQueue {
|
||||||
--(*ptr);
|
--(*ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool isIncluded(const queue_s *q) {
|
||||||
|
uint8_t ptr = mRdPtr;
|
||||||
|
while (ptr != mWrPtr) {
|
||||||
|
if(mQueue[ptr].cmd == q->cmd) {
|
||||||
|
if(mQueue[ptr].iv->id == q->iv->id)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::array<queue_s, N> mQueue;
|
std::array<queue_s, N> mQueue;
|
||||||
uint8_t mWrPtr = 0;
|
uint8_t mWrPtr = 0;
|
||||||
|
|
|
@ -57,7 +57,6 @@ class HistoryData {
|
||||||
|
|
||||||
void tickerSecond() {
|
void tickerSecond() {
|
||||||
float curPwr = 0;
|
float curPwr = 0;
|
||||||
//float maxPwr = 0;
|
|
||||||
float yldDay = -0.1;
|
float yldDay = -0.1;
|
||||||
uint32_t ts = 0;
|
uint32_t ts = 0;
|
||||||
|
|
||||||
|
@ -67,7 +66,6 @@ class HistoryData {
|
||||||
if (iv == NULL)
|
if (iv == NULL)
|
||||||
continue;
|
continue;
|
||||||
curPwr += iv->getChannelFieldValue(CH0, FLD_PAC, rec);
|
curPwr += iv->getChannelFieldValue(CH0, FLD_PAC, rec);
|
||||||
//maxPwr += iv->getChannelFieldValue(CH0, FLD_MP, rec);
|
|
||||||
yldDay += iv->getChannelFieldValue(CH0, FLD_YD, rec);
|
yldDay += iv->getChannelFieldValue(CH0, FLD_YD, rec);
|
||||||
if (rec->ts > ts)
|
if (rec->ts > ts)
|
||||||
ts = rec->ts;
|
ts = rec->ts;
|
||||||
|
@ -81,8 +79,6 @@ class HistoryData {
|
||||||
if (curPwr > mMaximumDay)
|
if (curPwr > mMaximumDay)
|
||||||
mMaximumDay = roundf(curPwr);
|
mMaximumDay = roundf(curPwr);
|
||||||
}
|
}
|
||||||
//if (maxPwr > 0)
|
|
||||||
// mMaximumDay = roundf(maxPwr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((++mCurPwrDay.loopCnt % mCurPwrDay.refreshCycle) == 0) {
|
if ((++mCurPwrDay.loopCnt % mCurPwrDay.refreshCycle) == 0) {
|
||||||
|
|
|
@ -577,6 +577,7 @@ class RestApi {
|
||||||
obj[F("rstMid")] = (bool)mConfig->inst.rstYieldMidNight;
|
obj[F("rstMid")] = (bool)mConfig->inst.rstYieldMidNight;
|
||||||
obj[F("rstNotAvail")] = (bool)mConfig->inst.rstValsNotAvail;
|
obj[F("rstNotAvail")] = (bool)mConfig->inst.rstValsNotAvail;
|
||||||
obj[F("rstComStop")] = (bool)mConfig->inst.rstValsCommStop;
|
obj[F("rstComStop")] = (bool)mConfig->inst.rstValsCommStop;
|
||||||
|
obj[F("rstComStart")] = (bool)mConfig->inst.rstValsCommStart;
|
||||||
obj[F("strtWthtTm")] = (bool)mConfig->inst.startWithoutTime;
|
obj[F("strtWthtTm")] = (bool)mConfig->inst.startWithoutTime;
|
||||||
obj[F("rdGrid")] = (bool)mConfig->inst.readGrid;
|
obj[F("rdGrid")] = (bool)mConfig->inst.readGrid;
|
||||||
obj[F("rstMaxMid")] = (bool)mConfig->inst.rstMaxValsMidNight;
|
obj[F("rstMaxMid")] = (bool)mConfig->inst.rstMaxValsMidNight;
|
||||||
|
|
|
@ -130,7 +130,11 @@
|
||||||
<div class="col-4"><input type="checkbox" name="invRstMid"/></div>
|
<div class="col-4"><input type="checkbox" name="invRstMid"/></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-3">
|
<div class="row mb-3">
|
||||||
<div class="col-8 mb-2">{#INV_PAUSE_SUNSET}</div>
|
<div class="col-8 mb-2">{#INV_RESET_SUNRISE}</div>
|
||||||
|
<div class="col-4"><input type="checkbox" name="invRstComStart"/></div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col-8 mb-2">{#INV_RESET_SUNSET}</div>
|
||||||
<div class="col-4"><input type="checkbox" name="invRstComStop"/></div>
|
<div class="col-4"><input type="checkbox" name="invRstComStop"/></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-3">
|
<div class="row mb-3">
|
||||||
|
@ -670,7 +674,7 @@
|
||||||
function ivGlob(obj) {
|
function ivGlob(obj) {
|
||||||
for(var i of [["invInterval", "interval"]])
|
for(var i of [["invInterval", "interval"]])
|
||||||
document.getElementsByName(i[0])[0].value = obj[i[1]];
|
document.getElementsByName(i[0])[0].value = obj[i[1]];
|
||||||
for(var i of ["Mid", "ComStop", "NotAvail", "MaxMid"])
|
for(var i of ["Mid", "ComStop", "ComStart", "NotAvail", "MaxMid"])
|
||||||
document.getElementsByName("invRst"+i)[0].checked = obj["rst" + i];
|
document.getElementsByName("invRst"+i)[0].checked = obj["rst" + i];
|
||||||
document.getElementsByName("strtWthtTm")[0].checked = obj["strtWthtTm"];
|
document.getElementsByName("strtWthtTm")[0].checked = obj["strtWthtTm"];
|
||||||
document.getElementsByName("rdGrid")[0].checked = obj["rdGrid"];
|
document.getElementsByName("rdGrid")[0].checked = obj["rdGrid"];
|
||||||
|
|
|
@ -324,10 +324,15 @@
|
||||||
"de": "Werte und Gesamtertrag um Mitternacht zurücksetzen"
|
"de": "Werte und Gesamtertrag um Mitternacht zurücksetzen"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"token": "INV_PAUSE_SUNSET",
|
"token": "INV_RESET_SUNSET",
|
||||||
"en": "Reset values at sunset",
|
"en": "Reset values at sunset",
|
||||||
"de": "Werte bei Sonnenuntergang zurücksetzen"
|
"de": "Werte bei Sonnenuntergang zurücksetzen"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"token": "INV_RESET_SUNRISE",
|
||||||
|
"en": "Reset values at sunrise",
|
||||||
|
"de": "Werte bei Sonnenaufgang zurücksetzen"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"token": "INV_RESET_NOT_AVAIL",
|
"token": "INV_RESET_NOT_AVAIL",
|
||||||
"en": "Reset values when inverter status is 'not available'",
|
"en": "Reset values when inverter status is 'not available'",
|
||||||
|
|
|
@ -500,6 +500,7 @@ class Web {
|
||||||
mConfig->inst.sendInterval = request->arg("invInterval").toInt();
|
mConfig->inst.sendInterval = request->arg("invInterval").toInt();
|
||||||
mConfig->inst.rstYieldMidNight = (request->arg("invRstMid") == "on");
|
mConfig->inst.rstYieldMidNight = (request->arg("invRstMid") == "on");
|
||||||
mConfig->inst.rstValsCommStop = (request->arg("invRstComStop") == "on");
|
mConfig->inst.rstValsCommStop = (request->arg("invRstComStop") == "on");
|
||||||
|
mConfig->inst.rstValsCommStart = (request->arg("invRstComStart") == "on");
|
||||||
mConfig->inst.rstValsNotAvail = (request->arg("invRstNotAvail") == "on");
|
mConfig->inst.rstValsNotAvail = (request->arg("invRstNotAvail") == "on");
|
||||||
mConfig->inst.startWithoutTime = (request->arg("strtWthtTm") == "on");
|
mConfig->inst.startWithoutTime = (request->arg("strtWthtTm") == "on");
|
||||||
mConfig->inst.readGrid = (request->arg("rdGrid") == "on");
|
mConfig->inst.readGrid = (request->arg("rdGrid") == "on");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue