mirror of https://github.com/lumapu/ahoy.git
12 changed files with 234 additions and 491 deletions
@ -1,94 +0,0 @@ |
|||||
|
|
||||
#include "plugins/history.h" |
|
||||
|
|
||||
#include "appInterface.h" |
|
||||
#include "config/config.h" |
|
||||
#include "utils/dbg.h" |
|
||||
|
|
||||
void TotalPowerHistory::setup(IApp *app, HmSystemType *sys, settings_t *config) { |
|
||||
mApp = app; |
|
||||
mSys = sys; |
|
||||
mConfig = config; |
|
||||
mRefreshCycle = mConfig->inst.sendInterval; |
|
||||
mMaximumDay = 0; |
|
||||
|
|
||||
// Debug
|
|
||||
//for (uint16_t i = 0; i < HISTORY_DATA_ARR_LENGTH *1.5; i++) {
|
|
||||
// addValue(i);
|
|
||||
//}
|
|
||||
} |
|
||||
|
|
||||
void TotalPowerHistory::tickerSecond() { |
|
||||
++mLoopCnt; |
|
||||
if ((mLoopCnt % mRefreshCycle) == 0) { |
|
||||
//DPRINTLN(DBG_DEBUG,F("TotalPowerHistory::tickerSecond > refreshCycle" + String(mRefreshCycle) + "|" + String(mLoopCnt) + "|" + String(mRefreshCycle % mLoopCnt));
|
|
||||
mLoopCnt = 0; |
|
||||
float totalPower = 0; |
|
||||
float totalPowerDay = 0; |
|
||||
Inverter<> *iv; |
|
||||
record_t<> *rec; |
|
||||
for (uint8_t i = 0; i < mSys->getNumInverters(); i++) { |
|
||||
iv = mSys->getInverterByPos(i); |
|
||||
rec = iv->getRecordStruct(RealTimeRunData_Debug); |
|
||||
if (iv == NULL) |
|
||||
continue; |
|
||||
totalPower += iv->getChannelFieldValue(CH0, FLD_PAC, rec); |
|
||||
totalPowerDay += iv->getChannelFieldValue(CH0, FLD_MP, rec); |
|
||||
} |
|
||||
if (totalPower > 0) { |
|
||||
uint16_t iTotalPower = roundf(totalPower); |
|
||||
DPRINTLN(DBG_DEBUG, F("[TotalPowerHistory]: addValue(iTotalPower)=") + String(iTotalPower)); |
|
||||
addValue(iTotalPower); |
|
||||
} |
|
||||
if (totalPowerDay > 0) { |
|
||||
mMaximumDay = roundf(totalPowerDay); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
void YieldDayHistory::setup(IApp *app, HmSystemType *sys, settings_t *config) { |
|
||||
mApp = app; |
|
||||
mSys = sys; |
|
||||
mConfig = config; |
|
||||
mRefreshCycle = 60; // every minute
|
|
||||
mDayStored = false; |
|
||||
}; |
|
||||
|
|
||||
void YieldDayHistory::tickerSecond() { |
|
||||
++mLoopCnt; |
|
||||
if ((mLoopCnt % mRefreshCycle) == 0) { |
|
||||
mLoopCnt = 0; |
|
||||
// check for sunset. if so store yield of day once
|
|
||||
uint32_t sunsetTime = mApp->getSunset(); |
|
||||
uint32_t sunriseTime = mApp->getSunrise(); |
|
||||
uint32_t currentTime = mApp->getTimestamp(); |
|
||||
DPRINTLN(DBG_DEBUG,F("[YieldDayHistory] current | rise | set -> ") + String(currentTime) + " | " + String(sunriseTime) + " | " + String(sunsetTime)); |
|
||||
|
|
||||
if (currentTime > sunsetTime) { |
|
||||
if (!mDayStored) { |
|
||||
DPRINTLN(DBG_DEBUG,F("currentTime > sunsetTime ") + String(currentTime) + " > " + String(sunsetTime)); |
|
||||
float totalYieldDay = -0.1; |
|
||||
Inverter<> *iv; |
|
||||
record_t<> *rec; |
|
||||
for (uint8_t i = 0; i < mSys->getNumInverters(); i++) { |
|
||||
iv = mSys->getInverterByPos(i); |
|
||||
rec = iv->getRecordStruct(RealTimeRunData_Debug); |
|
||||
if (iv == NULL) |
|
||||
continue; |
|
||||
totalYieldDay += iv->getChannelFieldValue(CH0, FLD_YD, rec); |
|
||||
} |
|
||||
if (totalYieldDay > 0) { |
|
||||
uint16_t iTotalYieldDay = roundf(totalYieldDay); |
|
||||
DPRINTLN(DBG_DEBUG,F("addValue(iTotalYieldDay)=") + String(iTotalYieldDay)); |
|
||||
addValue(iTotalYieldDay); |
|
||||
mDayStored = true; |
|
||||
} |
|
||||
} |
|
||||
} else { |
|
||||
if (currentTime > sunriseTime) { |
|
||||
DPRINTLN(DBG_DEBUG,F("currentTime > sunriseTime ") + String(currentTime) + " > " + String(sunriseTime)); |
|
||||
mDayStored = false; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
@ -1,86 +1,123 @@ |
|||||
|
//-----------------------------------------------------------------------------
|
||||
|
// 2024 Ahoy, https://ahoydtu.de
|
||||
|
// Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed
|
||||
|
//-----------------------------------------------------------------------------
|
||||
|
|
||||
#ifndef __HISTORY_DATA_H__ |
#ifndef __HISTORY_DATA_H__ |
||||
#define __HISTORY_DATA_H__ |
#define __HISTORY_DATA_H__ |
||||
|
|
||||
#include "utils/helper.h" |
#include <array> |
||||
#include "defines.h" |
#include "../appInterface.h" |
||||
#include "hm/hmSystem.h" |
#include "../hm/hmSystem.h" |
||||
|
#include "../utils/helper.h" |
||||
typedef HmSystem<MAX_NUM_INVERTERS> HmSystemType; |
|
||||
class IApp; |
|
||||
|
|
||||
#define HISTORY_DATA_ARR_LENGTH 256 |
#define HISTORY_DATA_ARR_LENGTH 256 |
||||
|
|
||||
class HistoryData { |
enum class HistoryStorageType : uint8_t { |
||||
public: |
POWER, |
||||
HistoryData() { |
YIELD |
||||
for (int i = 0; i < HISTORY_DATA_ARR_LENGTH; i++) |
|
||||
m_dataArr[i] = 0; |
|
||||
m_listIdx = 0; |
|
||||
m_dispIdx = 0; |
|
||||
m_wrapped = false; |
|
||||
}; |
|
||||
void addValue(uint16_t value) |
|
||||
{ |
|
||||
if (m_wrapped) // after 1st time array wrap we have to increas the display index
|
|
||||
m_dispIdx = (m_listIdx + 1) % (HISTORY_DATA_ARR_LENGTH); |
|
||||
m_dataArr[m_listIdx] = value; |
|
||||
m_listIdx = (m_listIdx + 1) % (HISTORY_DATA_ARR_LENGTH); |
|
||||
if (m_listIdx == 0) |
|
||||
m_wrapped = true; |
|
||||
}; |
|
||||
|
|
||||
uint16_t valueAt(int i){ |
|
||||
uint16_t idx = m_dispIdx + i; |
|
||||
idx = idx % HISTORY_DATA_ARR_LENGTH; |
|
||||
uint16_t value = m_dataArr[idx]; |
|
||||
return value; |
|
||||
}; |
|
||||
|
|
||||
private: |
|
||||
uint16_t m_dataArr[HISTORY_DATA_ARR_LENGTH + 1]; // ring buffer for watt history
|
|
||||
uint16_t m_listIdx; // index for next Element to write into WattArr
|
|
||||
uint16_t m_dispIdx; // index for 1st Element to display from WattArr
|
|
||||
bool m_wrapped; |
|
||||
}; |
}; |
||||
|
|
||||
class TotalPowerHistory : public HistoryData { |
template<class HMSYSTEM> |
||||
public: |
class HistoryData { |
||||
TotalPowerHistory() : HistoryData() { |
private: |
||||
mLoopCnt = 0; |
struct storage_t { |
||||
}; |
uint16_t refreshCycle; |
||||
|
uint16_t loopCnt; |
||||
void setup(IApp *app, HmSystemType *sys, settings_t *config); |
uint16_t listIdx; // index for next Element to write into WattArr
|
||||
void tickerSecond(); |
uint16_t dispIdx; // index for 1st Element to display from WattArr
|
||||
uint16_t getMaximumDay() { return mMaximumDay; } |
bool wrapped; |
||||
|
// ring buffer for watt history
|
||||
private: |
std::array<uint16_t, HISTORY_DATA_ARR_LENGTH + 1> data; |
||||
IApp *mApp; |
|
||||
HmSystemType *mSys; |
void reset() { |
||||
settings *mSettings; |
loopCnt = 0; |
||||
settings_t *mConfig; |
listIdx = 0; |
||||
uint16_t mRefreshCycle; |
dispIdx = 0; |
||||
uint16_t mLoopCnt; |
wrapped = false; |
||||
|
for(uint16_t i = 0; i < (HISTORY_DATA_ARR_LENGTH + 1); i++) { |
||||
uint16_t mMaximumDay; |
data[i] = 0; |
||||
}; |
} |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
public: |
||||
|
void setup(IApp *app, HMSYSTEM *sys, settings_t *config, uint32_t *ts) { |
||||
|
mApp = app; |
||||
|
mSys = sys; |
||||
|
mConfig = config; |
||||
|
mTs = ts; |
||||
|
|
||||
|
mCurPwr.reset(); |
||||
|
mCurPwr.refreshCycle = mConfig->inst.sendInterval; |
||||
|
mYieldDay.reset(); |
||||
|
mYieldDay.refreshCycle = 60; |
||||
|
} |
||||
|
|
||||
|
void tickerSecond() { |
||||
|
Inverter<> *iv; |
||||
|
record_t<> *rec; |
||||
|
float curPwr = 0; |
||||
|
float maxPwr = 0; |
||||
|
float yldDay = -0.1; |
||||
|
for (uint8_t i = 0; i < mSys->getNumInverters(); i++) { |
||||
|
iv = mSys->getInverterByPos(i); |
||||
|
rec = iv->getRecordStruct(RealTimeRunData_Debug); |
||||
|
if (iv == NULL) |
||||
|
continue; |
||||
|
curPwr += iv->getChannelFieldValue(CH0, FLD_PAC, rec); |
||||
|
maxPwr += iv->getChannelFieldValue(CH0, FLD_MP, rec); |
||||
|
yldDay += iv->getChannelFieldValue(CH0, FLD_YD, rec); |
||||
|
} |
||||
|
|
||||
|
if ((++mCurPwr.loopCnt % mCurPwr.refreshCycle) == 0) { |
||||
|
mCurPwr.loopCnt = 0; |
||||
|
if (curPwr > 0) |
||||
|
addValue(&mCurPwr, roundf(curPwr)); |
||||
|
if (maxPwr > 0) |
||||
|
mMaximumDay = roundf(maxPwr); |
||||
|
} |
||||
|
|
||||
|
if (*mTs > mApp->getSunset()) { |
||||
|
if ((!mDayStored) && (yldDay > 0)) { |
||||
|
addValue(&mYieldDay, roundf(yldDay)); |
||||
|
mDayStored = true; |
||||
|
} |
||||
|
} else if (*mTs > mApp->getSunrise()) |
||||
|
mDayStored = false; |
||||
|
} |
||||
|
|
||||
|
uint16_t valueAt(HistoryStorageType type, uint16_t i) { |
||||
|
settings_t *s = (HistoryStorageType::POWER == type) ? &mCurPwr : &mYieldDay; |
||||
|
uint16_t idx = (s->dispIdx + i) % HISTORY_DATA_ARR_LENGTH; |
||||
|
return s->data[idx]; |
||||
|
} |
||||
|
|
||||
|
uint16_t getMaximumDay() { |
||||
|
return mMaximumDay; |
||||
|
} |
||||
|
|
||||
|
private: |
||||
|
void addValue(storage_t *s, uint16_t value) { |
||||
|
if (s->wrapped) // after 1st time array wrap we have to increase the display index
|
||||
|
s->dispIdx = (s->listIdx + 1) % (HISTORY_DATA_ARR_LENGTH); |
||||
|
s->data[s->listIdx] = value; |
||||
|
s->listIdx = (s->listIdx + 1) % (HISTORY_DATA_ARR_LENGTH); |
||||
|
if (s->listIdx == 0) |
||||
|
s->wrapped = true; |
||||
|
} |
||||
|
|
||||
|
private: |
||||
|
IApp *mApp; |
||||
|
HMSYSTEM *mSys; |
||||
|
settings *mSettings; |
||||
|
settings_t *mConfig; |
||||
|
uint32_t *mTs; |
||||
|
|
||||
class YieldDayHistory : public HistoryData { |
storage_t mCurPwr; |
||||
public: |
storage_t mYieldDay; |
||||
YieldDayHistory() : HistoryData(){ |
bool mDayStored = false; |
||||
mLoopCnt = 0; |
uint16_t mMaximumDay = 0; |
||||
}; |
|
||||
|
|
||||
void setup(IApp *app, HmSystemType *sys, settings_t *config); |
|
||||
void tickerSecond(); |
|
||||
|
|
||||
private: |
|
||||
IApp *mApp; |
|
||||
HmSystemType *mSys; |
|
||||
settings *mSettings; |
|
||||
settings_t *mConfig; |
|
||||
uint16_t mRefreshCycle; |
|
||||
uint16_t mLoopCnt; |
|
||||
bool mDayStored; |
|
||||
}; |
}; |
||||
|
|
||||
#endif |
#endif |
Loading…
Reference in new issue