diff --git a/src/CHANGES.md b/src/CHANGES.md index 4586fc863..53485e032 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -4,6 +4,7 @@ * 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) +* fixed calculation of max AC power (API, MqTT) ## 0.8.114 - 2024-04-29 * fix ESP8266 compile diff --git a/src/app.cpp b/src/app.cpp index b362057ac..dd7048e90 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -94,6 +94,7 @@ void app::setup() { mDbgSyslog.setup(mConfig); // be sure to init after mWeb.setup (webSerial uses also debug callback) #endif // Plugins + mMaxPower.setup(&mTimestamp, mConfig->inst.sendInterval); #if defined(PLUGIN_DISPLAY) if (DISP_TYPE_T0_NONE != mConfig->plugin.display.type) #if defined(ESP32) diff --git a/src/app.h b/src/app.h index a3692d209..634696f25 100644 --- a/src/app.h +++ b/src/app.h @@ -31,6 +31,7 @@ #include "utils/syslog.h" #include "web/RestApi.h" #include "web/Protection.h" +#include "plugins/MaxPower.h" #if defined(ENABLE_HISTORY) #include "plugins/history.h" #endif /*ENABLE_HISTORY*/ @@ -309,6 +310,10 @@ class app : public IApp, public ah::Scheduler { } } + float getTotalMaxPower(void) override { + return mMaxPower.getTotalMaxPower(); + } + uint16_t getHistoryValue(uint8_t type, uint16_t i) override { #if defined(ENABLE_HISTORY) return mHistory.valueAt((HistoryStorageType)type, i); @@ -356,6 +361,7 @@ class app : public IApp, public ah::Scheduler { void zeroIvValues(bool checkAvail = false, bool skipYieldDay = true); void payloadEventListener(uint8_t cmd, Inverter<> *iv) { + mMaxPower.payloadEvent(cmd, iv); #if defined(ENABLE_MQTT) if (mMqttEnabled) mMqtt.payloadEventListener(cmd, iv); @@ -457,6 +463,7 @@ class app : public IApp, public ah::Scheduler { uint32_t mSunrise = 0, mSunset = 0; // plugins + MaxPower mMaxPower; #if defined(PLUGIN_DISPLAY) DisplayType mDisplay; DisplayData mDispData; diff --git a/src/appInterface.h b/src/appInterface.h index a5f4d081d..f2292ec8a 100644 --- a/src/appInterface.h +++ b/src/appInterface.h @@ -64,6 +64,7 @@ class IApp { virtual void resetLockTimeout(void) = 0; virtual bool isProtected(const char *clientIp, const char *token, bool askedFromWeb) const = 0; + virtual float getTotalMaxPower(void) = 0; virtual uint16_t getHistoryValue(uint8_t type, uint16_t i) = 0; virtual uint32_t getHistoryPeriod(uint8_t type) = 0; virtual uint16_t getHistoryMaxDay() = 0; diff --git a/src/hm/Communication.h b/src/hm/Communication.h index 5fd3b4871..c48815357 100644 --- a/src/hm/Communication.h +++ b/src/hm/Communication.h @@ -159,8 +159,6 @@ class Communication : public CommQueue<> { mFirstTry = false; mHeu.evalTxChQuality(q->iv, false, 0, 0); mHeu.getTxCh(q->iv); - //q->iv->radioStatistics.rxFailNoAnser++; // should only be one of fail or retransmit. - //q->iv->radioStatistics.txCnt--; q->iv->radioStatistics.retransmits++; q->iv->radio->mRadioWaitTime.stopTimeMonitor(); mState = States::START; diff --git a/src/plugins/MaxPower.h b/src/plugins/MaxPower.h new file mode 100644 index 000000000..8e2d4e37e --- /dev/null +++ b/src/plugins/MaxPower.h @@ -0,0 +1,56 @@ +//----------------------------------------------------------------------------- +// 2024 Ahoy, https://github.com/lumpapu/ahoy +// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/4.0/deed +//----------------------------------------------------------------------------- + +#ifndef __MAX_VALUE__ +#define __MAX_VALUE__ +#pragma once + +#include +#include +#include "../hm/hmDefines.h" + +template +class MaxPower { + public: + MaxPower() { + mTs = nullptr; + mMaxDiff = 60; + mValues.fill(std::make_pair(0, 0.0)); + } + + void setup(uint32_t *ts, uint16_t interval) { + mTs = ts; + mMaxDiff = interval * 4; + } + + void payloadEvent(uint8_t cmd, Inverter<> *iv) { + if(RealTimeRunData_Debug != cmd) + return; + + if(iv->id >= MAX_NUM_INVERTERS) + return; + + record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); + mValues[iv->id] = std::make_pair(*mTs, iv->getChannelFieldValue(CH0, FLD_PAC, rec)); + } + + T getTotalMaxPower(void) { + T val = 0; + for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i ++) { + if((mValues[i].first + mMaxDiff) >= *mTs) + val += mValues[i].second; + else if(mValues[i].first > 0) + return 0; // old data + } + return val; + } + + private: + uint32_t *mTs; + uint32_t mMaxDiff; + std::array, MAX_NUM_INVERTERS> mValues; +}; + +#endif diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index bd34a5196..4ce2b76c1 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -62,7 +62,7 @@ class PubMqtt { mUptime = uptime; mIntervalTimeout = 1; - SendIvData.setup(sys, utcTs, &mSendList); + SendIvData.setup(app, sys, utcTs, &mSendList); SendIvData.setPublishFunc([this](const char *subTopic, const char *payload, bool retained, uint8_t qos) { publish(subTopic, payload, retained, true, qos); }); diff --git a/src/publisher/pubMqttIvData.h b/src/publisher/pubMqttIvData.h index cd212aa48..aa221be7f 100644 --- a/src/publisher/pubMqttIvData.h +++ b/src/publisher/pubMqttIvData.h @@ -24,7 +24,8 @@ class PubMqttIvData { public: PubMqttIvData() : mTotal{}, mSubTopic{}, mVal{} {} - void setup(HMSYSTEM *sys, uint32_t *utcTs, std::queue *sendList) { + void setup(IApp *app, HMSYSTEM *sys, uint32_t *utcTs, std::queue *sendList) { + mApp = app; mSys = sys; mUtcTimestamp = utcTs; mSendList = sendList; @@ -168,9 +169,6 @@ class PubMqttIvData { case FLD_PDC: mTotal[3] += mIv->getValue(mPos, rec); break; - case FLD_MP: - mTotal[4] += mIv->getValue(mPos, rec); - break; } } else mAllTotalFound = false; @@ -261,6 +259,7 @@ class PubMqttIvData { case 4: fieldId = FLD_MP; retained = false; + mTotal[4] = mApp->getTotalMaxPower(); break; } snprintf(mSubTopic.data(), mSubTopic.size(), "total/%s", fields[fieldId]); @@ -274,6 +273,9 @@ class PubMqttIvData { } } + private: + IApp *mApp = nullptr; + HMSYSTEM *mSys = nullptr; uint32_t *mUtcTimestamp = nullptr; pubMqttPublisherType mPublish; diff --git a/src/web/RestApi.h b/src/web/RestApi.h index b7e339844..375c0e522 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -105,7 +105,6 @@ class RestApi { else if(path == "live") getLive(request,root); else if (path == "powerHistory") getPowerHistory(request, root); else if (path == "powerHistoryDay") getPowerHistoryDay(request, root); - else if (path == "yieldDayHistory") getYieldDayHistory(request, root); else { if(path.substring(0, 12) == "inverter/id/") getInverter(root, request->url().substring(17).toInt()); @@ -298,7 +297,6 @@ class RestApi { #if defined(ENABLE_HISTORY) ep[F("powerHistory")] = url + F("powerHistory"); ep[F("powerHistoryDay")] = url + F("powerHistoryDay"); - ep[F("yieldDayHistory")] = url + F("yieldDayHistory"); #endif } @@ -916,6 +914,7 @@ class RestApi { obj[F("fld_units")][fld] = String(units[fieldUnits[dcList[fld]]]); obj[F("fld_names")][fld] = String(fields[dcList[fld]]); } + obj[F("max_total_pwr")] = mApp->getTotalMaxPower(); Inverter<> *iv; for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i ++) {