mirror of
https://github.com/lumapu/ahoy.git
synced 2025-07-31 06:58:24 +02:00
0.8.1030004
This commit is contained in:
parent
4eb79ff7dc
commit
4c5e805370
8 changed files with 600 additions and 1643 deletions
72
src/app.cpp
72
src/app.cpp
|
@ -115,6 +115,7 @@ void app::setup() {
|
||||||
mMqttEnabled = (mConfig->mqtt.broker[0] > 0);
|
mMqttEnabled = (mConfig->mqtt.broker[0] > 0);
|
||||||
if (mMqttEnabled) {
|
if (mMqttEnabled) {
|
||||||
mMqtt.setup(this, &mConfig->mqtt, mConfig->sys.deviceName, mVersion, &mSys, &mTimestamp, &mUptime);
|
mMqtt.setup(this, &mConfig->mqtt, mConfig->sys.deviceName, mVersion, &mSys, &mTimestamp, &mUptime);
|
||||||
|
mMqtt.setConnectionCb(std::bind(&app::mqttConnectCb, this));
|
||||||
mMqtt.setSubscriptionCb(std::bind(&app::mqttSubRxCb, this, std::placeholders::_1));
|
mMqtt.setSubscriptionCb(std::bind(&app::mqttSubRxCb, this, std::placeholders::_1));
|
||||||
mCommunication.addAlarmListener([this](Inverter<> *iv) { mMqtt.alarmEvent(iv); });
|
mCommunication.addAlarmListener([this](Inverter<> *iv) { mMqtt.alarmEvent(iv); });
|
||||||
}
|
}
|
||||||
|
@ -145,7 +146,7 @@ void app::setup() {
|
||||||
|
|
||||||
// Plugin ZeroExport
|
// Plugin ZeroExport
|
||||||
#if defined(PLUGIN_ZEROEXPORT)
|
#if defined(PLUGIN_ZEROEXPORT)
|
||||||
mZeroExport.setup(&mConfig->plugin.zeroExport, &mSys, mConfig, &mApi, &mMqtt);
|
mZeroExport.setup(this, &mTimestamp, &mConfig->plugin.zeroExport, &mSys, mConfig, &mApi, &mMqtt);
|
||||||
#endif /*PLUGIN_ZEROEXPORT*/
|
#endif /*PLUGIN_ZEROEXPORT*/
|
||||||
// Plugin ZeroExport - Ende
|
// Plugin ZeroExport - Ende
|
||||||
|
|
||||||
|
@ -403,10 +404,6 @@ void app::tickMinute(void) {
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void app::tickMidnight(void) {
|
void app::tickMidnight(void) {
|
||||||
#if defined(PLUGIN_ZEROEXPORT)
|
|
||||||
mZeroExport.tickMidnight();
|
|
||||||
#endif /*defined(PLUGIN_ZEROEXPORT)*/
|
|
||||||
|
|
||||||
uint32_t localTime = gTimezone.toLocal(mTimestamp);
|
uint32_t localTime = gTimezone.toLocal(mTimestamp);
|
||||||
uint32_t nxtTrig = gTimezone.toUTC(localTime - (localTime % 86400) + 86400); // next midnight local time
|
uint32_t nxtTrig = gTimezone.toUTC(localTime - (localTime % 86400) + 86400); // next midnight local time
|
||||||
onceAt(std::bind(&app::tickMidnight, this), nxtTrig, "mid2");
|
onceAt(std::bind(&app::tickMidnight, this), nxtTrig, "mid2");
|
||||||
|
@ -439,6 +436,10 @@ void app::tickMidnight(void) {
|
||||||
mMqtt.tickerMidnight();
|
mMqtt.tickerMidnight();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(PLUGIN_ZEROEXPORT)
|
||||||
|
mZeroExport.tickMidnight();
|
||||||
|
#endif /*defined(PLUGIN_ZEROEXPORT)*/
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -619,6 +620,13 @@ void app::resetSystem(void) {
|
||||||
mNtpReceived = false;
|
mNtpReceived = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void app::mqttConnectCb(void) {
|
||||||
|
#if defined(PLUGIN_ZEROEXPORT)
|
||||||
|
mZeroExport.onMqttConnect();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void app::mqttSubRxCb(JsonObject obj) {
|
void app::mqttSubRxCb(JsonObject obj) {
|
||||||
mApi.ctrlRequest(obj);
|
mApi.ctrlRequest(obj);
|
||||||
|
@ -673,57 +681,3 @@ void app::updateLed(void) {
|
||||||
analogWrite(mConfig->led.led[2], led_off);
|
analogWrite(mConfig->led.led[2], led_off);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Plugin ZeroExport
|
|
||||||
#if defined(PLUGIN_ZEROEXPORT)
|
|
||||||
void app::zeroexport() {
|
|
||||||
return;
|
|
||||||
// TODO: aufr<66>umen
|
|
||||||
// TODO: umziehen nach loop
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
if (!mConfig->plugin.zeroExport.enabled ||
|
|
||||||
!mSys.getInverterByPos(mConfig->plugin.zeroExport.Iv)->isProducing()) { // check if plugin is enabled && indicate to send new value
|
|
||||||
mConfig->plugin.zeroExport.lastTime = millis(); // set last timestamp
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (millis() - mConfig->plugin.zeroExport.lastTime > mConfig->plugin.zeroExport.count_avg * 1000UL)
|
|
||||||
{
|
|
||||||
Inverter<> *iv = mSys.getInverterByPos(mConfig->plugin.zeroExport.Iv);
|
|
||||||
|
|
||||||
DynamicJsonDocument doc(512);
|
|
||||||
JsonObject object = doc.to<JsonObject>();
|
|
||||||
|
|
||||||
double nValue = round(mZeroExport.getPowertoSetnewValue());
|
|
||||||
double twoPerVal = nValue <= (iv->getMaxPower() / 100 * 2 );
|
|
||||||
|
|
||||||
if(mConfig->plugin.zeroExport.two_percent && (nValue <= twoPerVal))
|
|
||||||
nValue = twoPerVal;
|
|
||||||
|
|
||||||
if(mConfig->plugin.zeroExport.max_power <= nValue)
|
|
||||||
nValue = mConfig->plugin.zeroExport.max_power;
|
|
||||||
|
|
||||||
if(iv->actPowerLimit == nValue) {
|
|
||||||
mConfig->plugin.zeroExport.lastTime = millis(); // set last timestamp
|
|
||||||
return; // if PowerLimit same as befor, then skip
|
|
||||||
}
|
|
||||||
|
|
||||||
object["val"] = nValue;
|
|
||||||
object["id"] = mConfig->plugin.zeroExport.Iv;
|
|
||||||
object["path"] = "ctrl";
|
|
||||||
object["cmd"] = "limit_nonpersistent_absolute";
|
|
||||||
|
|
||||||
String data;
|
|
||||||
serializeJsonPretty(object, data);
|
|
||||||
DPRINTLN(DBG_INFO, data);
|
|
||||||
mApi.ctrlRequest(object);
|
|
||||||
|
|
||||||
mConfig->plugin.zeroExport.lastTime = millis(); // set last timestamp
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
// Plugin ZeroExport - Ende
|
|
||||||
|
|
|
@ -370,17 +370,12 @@ class app : public IApp, public ah::Scheduler {
|
||||||
updateLed();
|
updateLed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mqttConnectCb(void);
|
||||||
void mqttSubRxCb(JsonObject obj);
|
void mqttSubRxCb(JsonObject obj);
|
||||||
|
|
||||||
void setupLed();
|
void setupLed();
|
||||||
void updateLed();
|
void updateLed();
|
||||||
|
|
||||||
// Plugin ZeroExport
|
|
||||||
#if defined(PLUGIN_ZEROEXPORT)
|
|
||||||
void zeroexport();
|
|
||||||
#endif
|
|
||||||
// Plugin ZeroExport - Ende
|
|
||||||
|
|
||||||
void tickReboot(void) {
|
void tickReboot(void) {
|
||||||
DPRINTLN(DBG_INFO, F("Rebooting..."));
|
DPRINTLN(DBG_INFO, F("Rebooting..."));
|
||||||
ah::Scheduler::resetTicker();
|
ah::Scheduler::resetTicker();
|
||||||
|
|
|
@ -203,7 +203,7 @@ typedef struct {
|
||||||
// Plugin ZeroExport
|
// Plugin ZeroExport
|
||||||
#if defined(PLUGIN_ZEROEXPORT)
|
#if defined(PLUGIN_ZEROEXPORT)
|
||||||
|
|
||||||
#define ZEROEXPORT_DEV_POWERMETER
|
#define ZEROEXPORT_MAX_QUEUE_ENTRIES 64
|
||||||
#define ZEROEXPORT_MAX_GROUPS 6
|
#define ZEROEXPORT_MAX_GROUPS 6
|
||||||
#define ZEROEXPORT_GROUP_MAX_LEN_NAME 25
|
#define ZEROEXPORT_GROUP_MAX_LEN_NAME 25
|
||||||
#define ZEROEXPORT_GROUP_MAX_LEN_PM_URL 100
|
#define ZEROEXPORT_GROUP_MAX_LEN_PM_URL 100
|
||||||
|
@ -213,7 +213,7 @@ typedef struct {
|
||||||
#define ZEROEXPORT_GROUP_MAX_INVERTERS 3
|
#define ZEROEXPORT_GROUP_MAX_INVERTERS 3
|
||||||
#define ZEROEXPORT_POWERMETER_MAX_ERRORS 5
|
#define ZEROEXPORT_POWERMETER_MAX_ERRORS 5
|
||||||
#define ZEROEXPORT_DEF_INV_WAITINGTIME_MS 10000
|
#define ZEROEXPORT_DEF_INV_WAITINGTIME_MS 10000
|
||||||
#define ZEROEXPORT_GROUP_WR_LIMIT_MIN_DIFF 5
|
#define ZEROEXPORT_GROUP_WR_LIMIT_MIN_DIFF 2
|
||||||
#define ZEROEXPORT_POWERMETER_SHELLY
|
#define ZEROEXPORT_POWERMETER_SHELLY
|
||||||
//#define ZEROEXPORT_POWERMETER_TASMOTA
|
//#define ZEROEXPORT_POWERMETER_TASMOTA
|
||||||
#define ZEROEXPORT_POWERMETER_MQTT
|
#define ZEROEXPORT_POWERMETER_MQTT
|
||||||
|
@ -221,23 +221,6 @@ typedef struct {
|
||||||
#define ZEROEXPORT_POWERMETER_TIBBER
|
#define ZEROEXPORT_POWERMETER_TIBBER
|
||||||
#define ZEROEXPORT_POWERMETER_SHRDZM
|
#define ZEROEXPORT_POWERMETER_SHRDZM
|
||||||
|
|
||||||
enum class zeroExportState : uint8_t {
|
|
||||||
INIT,
|
|
||||||
WAITREFRESH,
|
|
||||||
GETINVERTERDATA,
|
|
||||||
BATTERYPROTECTION,
|
|
||||||
GETPOWERMETER,
|
|
||||||
CONTROLLER,
|
|
||||||
PROGNOSE,
|
|
||||||
AUFTEILEN,
|
|
||||||
SETREBOOT,
|
|
||||||
SETPOWER,
|
|
||||||
SETLIMIT,
|
|
||||||
EMERGENCY,
|
|
||||||
FINISH,
|
|
||||||
ERROR
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
None = 0,
|
None = 0,
|
||||||
Shelly = 1,
|
Shelly = 1,
|
||||||
|
@ -258,6 +241,20 @@ typedef enum {
|
||||||
L3Sum = 6,
|
L3Sum = 6,
|
||||||
} zeroExportInverterTarget_t;
|
} zeroExportInverterTarget_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
doNone = 0,
|
||||||
|
doRestart,
|
||||||
|
doTurnOn,
|
||||||
|
doTurnOff,
|
||||||
|
doActivePowerContr,
|
||||||
|
} zeroExportAction_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t group;
|
||||||
|
uint8_t inv;
|
||||||
|
uint8_t id;
|
||||||
|
} zeroExportQueue_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
bool enabled;
|
bool enabled;
|
||||||
int8_t id;
|
int8_t id;
|
||||||
|
@ -266,18 +263,13 @@ typedef struct {
|
||||||
uint16_t powerMax;
|
uint16_t powerMax;
|
||||||
//
|
//
|
||||||
|
|
||||||
int32_t power;
|
zeroExportAction_t action;
|
||||||
|
uint16_t power;
|
||||||
|
uint16_t MaxPower;
|
||||||
int32_t limit;
|
int32_t limit;
|
||||||
int32_t limitNew;
|
int32_t limitNew;
|
||||||
uint8_t waitAckSetLimit;
|
uint8_t waitAck;
|
||||||
uint8_t waitAckSetPower;
|
|
||||||
uint8_t waitAckSetReboot;
|
|
||||||
unsigned long limitTsp;
|
|
||||||
bool state;
|
|
||||||
//
|
//
|
||||||
int8_t doReboot;
|
|
||||||
int8_t doPower;
|
|
||||||
int8_t doLimit;
|
|
||||||
float dcVoltage;
|
float dcVoltage;
|
||||||
} zeroExportGroupInverter_t;
|
} zeroExportGroupInverter_t;
|
||||||
|
|
||||||
|
@ -298,18 +290,14 @@ typedef struct {
|
||||||
bool battEnabled;
|
bool battEnabled;
|
||||||
float battVoltageOn;
|
float battVoltageOn;
|
||||||
float battVoltageOff;
|
float battVoltageOff;
|
||||||
bool isChangedBattery;
|
|
||||||
// Advanced
|
// Advanced
|
||||||
int16_t setPoint;
|
int16_t setPoint;
|
||||||
uint8_t refresh;
|
uint8_t refresh;
|
||||||
int32_t power;
|
float power;
|
||||||
uint8_t powerTolerance;
|
uint8_t powerTolerance;
|
||||||
uint16_t powerMax;
|
uint16_t powerMax;
|
||||||
bool isChangedAdvanced;
|
|
||||||
//
|
//
|
||||||
|
|
||||||
zeroExportState state;
|
|
||||||
// zeroExportState stateNext;
|
|
||||||
unsigned long lastRun;
|
unsigned long lastRun;
|
||||||
unsigned long lastRefresh;
|
unsigned long lastRefresh;
|
||||||
uint16_t wait;
|
uint16_t wait;
|
||||||
|
@ -318,26 +306,16 @@ typedef struct {
|
||||||
int32_t pm_P1;
|
int32_t pm_P1;
|
||||||
int32_t pm_P2;
|
int32_t pm_P2;
|
||||||
int32_t pm_P3;
|
int32_t pm_P3;
|
||||||
bool publishPower = false;
|
|
||||||
|
|
||||||
bool battSwitch;
|
bool battSwitch;
|
||||||
|
|
||||||
// PID controller
|
// PID controller
|
||||||
int32_t eSum;
|
float eSum;
|
||||||
int32_t eSum1;
|
float eOld;
|
||||||
int32_t eSum2;
|
|
||||||
int32_t eSum3;
|
|
||||||
int32_t eOld;
|
|
||||||
int32_t eOld1;
|
|
||||||
int32_t eOld2;
|
|
||||||
int32_t eOld3;
|
|
||||||
float Kp;
|
float Kp;
|
||||||
float Ki;
|
float Ki;
|
||||||
float Kd;
|
float Kd;
|
||||||
int32_t y;
|
float y;
|
||||||
int32_t y1;
|
|
||||||
int32_t y2;
|
|
||||||
int32_t y3;
|
|
||||||
} zeroExportGroup_t;
|
} zeroExportGroup_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -347,18 +325,6 @@ typedef struct {
|
||||||
bool log_over_mqtt;
|
bool log_over_mqtt;
|
||||||
bool debug;
|
bool debug;
|
||||||
zeroExportGroup_t groups[ZEROEXPORT_MAX_GROUPS];
|
zeroExportGroup_t groups[ZEROEXPORT_MAX_GROUPS];
|
||||||
|
|
||||||
// uint8_t query_device; // 0 - Tibber, 1 - Shelly, 2 - other (rs232?)
|
|
||||||
// char monitor_url[ZEXPORT_ADDR_LEN];
|
|
||||||
// char json_path[ZEXPORT_ADDR_LEN];
|
|
||||||
// char tibber_pw[10]; // needed for tibber QWGH-ED12
|
|
||||||
// uint8_t Iv; // saves the inverter that is used for regulation
|
|
||||||
// float power_avg;
|
|
||||||
// uint8_t count_avg;
|
|
||||||
// double total_power;
|
|
||||||
// unsigned long lastTime; // tic toc
|
|
||||||
// double max_power;
|
|
||||||
// bool two_percent; // ask if not go lower then 2%
|
|
||||||
} zeroExport_t;
|
} zeroExport_t;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -712,19 +678,16 @@ class settings {
|
||||||
mCfg.plugin.zeroExport.groups[group].inverters[inv].powerMin = 10;
|
mCfg.plugin.zeroExport.groups[group].inverters[inv].powerMin = 10;
|
||||||
mCfg.plugin.zeroExport.groups[group].inverters[inv].powerMax = 600;
|
mCfg.plugin.zeroExport.groups[group].inverters[inv].powerMax = 600;
|
||||||
//
|
//
|
||||||
mCfg.plugin.zeroExport.groups[group].inverters[inv].waitAckSetLimit = false;
|
mCfg.plugin.zeroExport.groups[group].inverters[inv].waitAck = 0;
|
||||||
mCfg.plugin.zeroExport.groups[group].inverters[inv].waitAckSetPower = false;
|
mCfg.plugin.zeroExport.groups[group].inverters[inv].action = zeroExportAction_t::doNone;
|
||||||
mCfg.plugin.zeroExport.groups[group].inverters[inv].waitAckSetReboot = false;
|
|
||||||
mCfg.plugin.zeroExport.groups[group].inverters[inv].doReboot = -1;
|
|
||||||
mCfg.plugin.zeroExport.groups[group].inverters[inv].doPower = -1;
|
|
||||||
mCfg.plugin.zeroExport.groups[group].inverters[inv].doLimit = -1;
|
|
||||||
mCfg.plugin.zeroExport.groups[group].inverters[inv].dcVoltage = 0;
|
mCfg.plugin.zeroExport.groups[group].inverters[inv].dcVoltage = 0;
|
||||||
|
mCfg.plugin.zeroExport.groups[group].inverters[inv].limit = 0;
|
||||||
|
mCfg.plugin.zeroExport.groups[group].inverters[inv].limitNew = 0;
|
||||||
}
|
}
|
||||||
// Battery
|
// Battery
|
||||||
mCfg.plugin.zeroExport.groups[group].battEnabled = false;
|
mCfg.plugin.zeroExport.groups[group].battEnabled = false;
|
||||||
mCfg.plugin.zeroExport.groups[group].battVoltageOn = 0;
|
mCfg.plugin.zeroExport.groups[group].battVoltageOn = 0;
|
||||||
mCfg.plugin.zeroExport.groups[group].battVoltageOff = 0;
|
mCfg.plugin.zeroExport.groups[group].battVoltageOff = 0;
|
||||||
mCfg.plugin.zeroExport.groups[group].isChangedBattery = true;
|
|
||||||
// Advanced
|
// Advanced
|
||||||
mCfg.plugin.zeroExport.groups[group].setPoint = 0;
|
mCfg.plugin.zeroExport.groups[group].setPoint = 0;
|
||||||
mCfg.plugin.zeroExport.groups[group].refresh = 10;
|
mCfg.plugin.zeroExport.groups[group].refresh = 10;
|
||||||
|
@ -733,9 +696,7 @@ class settings {
|
||||||
mCfg.plugin.zeroExport.groups[group].Kp = -1;
|
mCfg.plugin.zeroExport.groups[group].Kp = -1;
|
||||||
mCfg.plugin.zeroExport.groups[group].Ki = 0;
|
mCfg.plugin.zeroExport.groups[group].Ki = 0;
|
||||||
mCfg.plugin.zeroExport.groups[group].Kd = 0;
|
mCfg.plugin.zeroExport.groups[group].Kd = 0;
|
||||||
mCfg.plugin.zeroExport.groups[group].isChangedAdvanced = true;
|
|
||||||
//
|
//
|
||||||
mCfg.plugin.zeroExport.groups[group].state = zeroExportState::INIT;
|
|
||||||
mCfg.plugin.zeroExport.groups[group].lastRun = 0;
|
mCfg.plugin.zeroExport.groups[group].lastRun = 0;
|
||||||
mCfg.plugin.zeroExport.groups[group].lastRefresh = 0;
|
mCfg.plugin.zeroExport.groups[group].lastRefresh = 0;
|
||||||
mCfg.plugin.zeroExport.groups[group].wait = 60000;
|
mCfg.plugin.zeroExport.groups[group].wait = 60000;
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
#define VERSION_MAJOR 0
|
#define VERSION_MAJOR 0
|
||||||
#define VERSION_MINOR 8
|
#define VERSION_MINOR 8
|
||||||
#define VERSION_PATCH 1030003
|
#define VERSION_PATCH 1030004
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t ch;
|
uint8_t ch;
|
||||||
|
|
|
@ -8,12 +8,15 @@
|
||||||
|
|
||||||
#include <AsyncJson.h>
|
#include <AsyncJson.h>
|
||||||
#include <HTTPClient.h>
|
#include <HTTPClient.h>
|
||||||
|
|
||||||
#include "config/settings.h"
|
#include "config/settings.h"
|
||||||
|
|
||||||
#if defined(ZEROEXPORT_POWERMETER_TIBBER)
|
#if defined(ZEROEXPORT_POWERMETER_TIBBER)
|
||||||
#include <base64.h>
|
#include <base64.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
#include "plugins/zeroExport/lib/sml.h"
|
#include "plugins/zeroExport/lib/sml.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -32,28 +35,46 @@ typedef struct {
|
||||||
|
|
||||||
class powermeter {
|
class powermeter {
|
||||||
public:
|
public:
|
||||||
powermeter() {
|
/** powermeter
|
||||||
}
|
* constructor
|
||||||
|
*/
|
||||||
|
powermeter() {}
|
||||||
|
|
||||||
~powermeter() {
|
/** ~powermeter
|
||||||
}
|
* destructor
|
||||||
|
*/
|
||||||
|
~powermeter() {}
|
||||||
|
|
||||||
bool setup(zeroExport_t *cfg, JsonObject *log /*Hier muss noch geklärt werden was gebraucht wird*/) {
|
/** setup
|
||||||
|
* Initialisierung
|
||||||
|
* @param *cfg
|
||||||
|
* @param *mqtt
|
||||||
|
* @param *log
|
||||||
|
* @returns void
|
||||||
|
*/
|
||||||
|
bool setup(zeroExport_t *cfg, PubMqttType *mqtt, JsonObject *log) {
|
||||||
mCfg = cfg;
|
mCfg = cfg;
|
||||||
|
mMqtt = mqtt;
|
||||||
mLog = log;
|
mLog = log;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** loop
|
/** loop
|
||||||
* abfrage der gruppen um die aktuellen Werte (Zähler) zu ermitteln.
|
* Arbeitsschleife
|
||||||
|
* @param void
|
||||||
|
* @returns void
|
||||||
|
* @todo emergency
|
||||||
*/
|
*/
|
||||||
void loop(unsigned long *tsp, bool *doLog) {
|
void loop(void) {
|
||||||
if (*tsp - mPreviousTsp <= 1000) return; // skip when it is to fast
|
if (millis() - mPreviousTsp <= 1000) return; // skip when it is to fast
|
||||||
mPreviousTsp = *tsp;
|
mPreviousTsp = millis();
|
||||||
|
|
||||||
PowermeterBuffer_t power;
|
PowermeterBuffer_t power;
|
||||||
|
|
||||||
for (u_short group = 0; group < ZEROEXPORT_MAX_GROUPS; group++) {
|
for (u_short group = 0; group < ZEROEXPORT_MAX_GROUPS; group++) {
|
||||||
|
if ((!mCfg->groups[group].enabled) || (mCfg->groups[group].sleep)) continue;
|
||||||
|
|
||||||
switch (mCfg->groups[group].pm_type) {
|
switch (mCfg->groups[group].pm_type) {
|
||||||
#if defined(ZEROEXPORT_POWERMETER_SHELLY)
|
#if defined(ZEROEXPORT_POWERMETER_SHELLY)
|
||||||
case zeroExportPowermeterType_t::Shelly:
|
case zeroExportPowermeterType_t::Shelly:
|
||||||
|
@ -89,7 +110,19 @@ class powermeter {
|
||||||
}
|
}
|
||||||
|
|
||||||
bufferWrite(power, group);
|
bufferWrite(power, group);
|
||||||
if (mCfg->debug) *doLog = true;
|
|
||||||
|
// MQTT - Powermeter
|
||||||
|
if (mMqtt->isConnected()) {
|
||||||
|
// P
|
||||||
|
mqttObj["Sum"] = ah::round1(power.P);
|
||||||
|
mqttObj["L1"] = ah::round1(power.P1);
|
||||||
|
mqttObj["L2"] = ah::round1(power.P2);
|
||||||
|
mqttObj["L3"] = ah::round1(power.P3);
|
||||||
|
mMqtt->publish(String("zero/state/groups/" + String(group) + "/powermeter/P").c_str(), mqttDoc.as<std::string>().c_str(), false);
|
||||||
|
mqttDoc.clear();
|
||||||
|
|
||||||
|
// W (TODO)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,10 +149,35 @@ class powermeter {
|
||||||
return avg;
|
return avg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void onMqttConnect(void) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void onMqttMessage(JsonObject obj) {
|
||||||
|
String topic = String(obj["topic"]);
|
||||||
|
|
||||||
|
#if defined(ZEROEXPORT_POWERMETER_MQTT)
|
||||||
|
// topic for powermeter?
|
||||||
|
for (uint8_t group = 0; group < ZEROEXPORT_MAX_GROUPS; group++) {
|
||||||
|
if (mCfg->groups[group].pm_type == zeroExportPowermeterType_t::Mqtt) {
|
||||||
|
// mLog["mqttDevice"] = "topicInverter";
|
||||||
|
if (!topic.equals(mCfg->groups[group].pm_jsonPath)) return;
|
||||||
|
mCfg->groups[group].pm_P = (int32_t)obj["val"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /*defined(ZEROEXPORT_POWERMETER_MQTT)*/
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
HTTPClient http;
|
HTTPClient http;
|
||||||
|
|
||||||
zeroExport_t *mCfg;
|
zeroExport_t *mCfg;
|
||||||
|
PubMqttType *mMqtt = nullptr;
|
||||||
JsonObject *mLog;
|
JsonObject *mLog;
|
||||||
|
|
||||||
unsigned long mPreviousTsp = 0;
|
unsigned long mPreviousTsp = 0;
|
||||||
|
@ -127,9 +185,13 @@ class powermeter {
|
||||||
PowermeterBuffer_t mPowermeterBuffer[ZEROEXPORT_MAX_GROUPS][5] = {0};
|
PowermeterBuffer_t mPowermeterBuffer[ZEROEXPORT_MAX_GROUPS][5] = {0};
|
||||||
short mPowermeterBufferPos[ZEROEXPORT_MAX_GROUPS] = {0};
|
short mPowermeterBufferPos[ZEROEXPORT_MAX_GROUPS] = {0};
|
||||||
|
|
||||||
|
StaticJsonDocument<512> mqttDoc; // DynamicJsonDocument mqttDoc(512);
|
||||||
|
JsonObject mqttObj = mqttDoc.to<JsonObject>();
|
||||||
|
|
||||||
// set HTTPClient header
|
/**
|
||||||
void setHeader(HTTPClient* h) {
|
*
|
||||||
|
*/
|
||||||
|
void setHeader(HTTPClient *h) {
|
||||||
h->setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
|
h->setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
|
||||||
h->setUserAgent("Ahoy-Agent");
|
h->setUserAgent("Ahoy-Agent");
|
||||||
// TODO: Ahoy-0.8.850024-zero
|
// TODO: Ahoy-0.8.850024-zero
|
||||||
|
@ -406,11 +468,9 @@ class powermeter {
|
||||||
*/
|
*/
|
||||||
const std::list<OBISHandler> smlHandlerList{
|
const std::list<OBISHandler> smlHandlerList{
|
||||||
{{0x01, 0x00, 0x10, 0x07, 0x00, 0xff}, &smlOBISW, &_powerMeterTotal}, // total - OBIS-Kennzahl für momentane Gesamtwirkleistung
|
{{0x01, 0x00, 0x10, 0x07, 0x00, 0xff}, &smlOBISW, &_powerMeterTotal}, // total - OBIS-Kennzahl für momentane Gesamtwirkleistung
|
||||||
|
|
||||||
{{0x01, 0x00, 0x24, 0x07, 0x00, 0xff}, &smlOBISW, &_powerMeter1Power}, // OBIS-Kennzahl für momentane Wirkleistung in Phase L1
|
{{0x01, 0x00, 0x24, 0x07, 0x00, 0xff}, &smlOBISW, &_powerMeter1Power}, // OBIS-Kennzahl für momentane Wirkleistung in Phase L1
|
||||||
{{0x01, 0x00, 0x38, 0x07, 0x00, 0xff}, &smlOBISW, &_powerMeter2Power}, // OBIS-Kennzahl für momentane Wirkleistung in Phase L2
|
{{0x01, 0x00, 0x38, 0x07, 0x00, 0xff}, &smlOBISW, &_powerMeter2Power}, // OBIS-Kennzahl für momentane Wirkleistung in Phase L2
|
||||||
{{0x01, 0x00, 0x4c, 0x07, 0x00, 0xff}, &smlOBISW, &_powerMeter3Power}, // OBIS-Kennzahl für momentane Wirkleistung in Phase L3
|
{{0x01, 0x00, 0x4c, 0x07, 0x00, 0xff}, &smlOBISW, &_powerMeter3Power}, // OBIS-Kennzahl für momentane Wirkleistung in Phase L3
|
||||||
|
|
||||||
{{0x01, 0x00, 0x01, 0x08, 0x00, 0xff}, &smlOBISWh, &_powerMeterImport},
|
{{0x01, 0x00, 0x01, 0x08, 0x00, 0xff}, &smlOBISWh, &_powerMeterImport},
|
||||||
{{0x01, 0x00, 0x02, 0x08, 0x00, 0xff}, &smlOBISWh, &_powerMeterExport}};
|
{{0x01, 0x00, 0x02, 0x08, 0x00, 0xff}, &smlOBISWh, &_powerMeterExport}};
|
||||||
|
|
||||||
|
@ -423,14 +483,12 @@ class powermeter {
|
||||||
logObj["mod"] = "getPowermeterWattsTibber";
|
logObj["mod"] = "getPowermeterWattsTibber";
|
||||||
|
|
||||||
String auth;
|
String auth;
|
||||||
if(strlen(mCfg->groups[group].pm_user) > 0 && strlen(mCfg->groups[group].pm_pass) > 0) {
|
if (strlen(mCfg->groups[group].pm_user) > 0 && strlen(mCfg->groups[group].pm_pass) > 0) {
|
||||||
auth = base64::encode(String(mCfg->groups[group].pm_user) + String(":") + String(mCfg->groups[group].pm_pass));
|
auth = base64::encode(String(mCfg->groups[group].pm_user) + String(":") + String(mCfg->groups[group].pm_pass));
|
||||||
snprintf(mCfg->groups[group].pm_user, ZEROEXPORT_GROUP_MAX_LEN_PM_USER, "%s", DEF_ZEXPORT);
|
snprintf(mCfg->groups[group].pm_user, ZEROEXPORT_GROUP_MAX_LEN_PM_USER, "%s", DEF_ZEXPORT);
|
||||||
snprintf(mCfg->groups[group].pm_pass, ZEROEXPORT_GROUP_MAX_LEN_PM_PASS, "%s", auth.c_str());
|
snprintf(mCfg->groups[group].pm_pass, ZEROEXPORT_GROUP_MAX_LEN_PM_PASS, "%s", auth.c_str());
|
||||||
//@TODO:mApp->saveSettings(false);
|
//@TODO:mApp->saveSettings(false);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
auth = mCfg->groups[group].pm_pass;
|
auth = mCfg->groups[group].pm_pass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -497,9 +555,7 @@ class powermeter {
|
||||||
|
|
||||||
String url =
|
String url =
|
||||||
String("http://") + String(mCfg->groups[group].pm_url) +
|
String("http://") + String(mCfg->groups[group].pm_url) +
|
||||||
String("/") + String(mCfg->groups[group].pm_jsonPath +
|
String("/") + String(mCfg->groups[group].pm_jsonPath + String("?user=") + String(mCfg->groups[group].pm_user) + String("&password=") + String(mCfg->groups[group].pm_pass));
|
||||||
String("?user=") + String(mCfg->groups[group].pm_user) +
|
|
||||||
String("&password=") + String(mCfg->groups[group].pm_pass));
|
|
||||||
|
|
||||||
http.begin(url);
|
http.begin(url);
|
||||||
|
|
||||||
|
@ -518,7 +574,6 @@ class powermeter {
|
||||||
if (!(result.P1 && result.P2 && result.P3)) {
|
if (!(result.P1 && result.P2 && result.P3)) {
|
||||||
result.P1 = result.P2 = result.P3 = result.P / 3;
|
result.P1 = result.P2 = result.P3 = result.P / 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
http.end();
|
http.end();
|
||||||
|
@ -527,6 +582,9 @@ class powermeter {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
void bufferWrite(PowermeterBuffer_t raw, short group) {
|
void bufferWrite(PowermeterBuffer_t raw, short group) {
|
||||||
mPowermeterBuffer[group][mPowermeterBufferPos[group]] = raw;
|
mPowermeterBuffer[group][mPowermeterBufferPos[group]] = raw;
|
||||||
mPowermeterBufferPos[group]++;
|
mPowermeterBufferPos[group]++;
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -27,6 +27,7 @@
|
||||||
#include "pubMqttIvData.h"
|
#include "pubMqttIvData.h"
|
||||||
|
|
||||||
typedef std::function<void(JsonObject)> subscriptionCb;
|
typedef std::function<void(JsonObject)> subscriptionCb;
|
||||||
|
typedef std::function<void(void)> connectionCb;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
bool running;
|
bool running;
|
||||||
|
@ -216,6 +217,10 @@ class PubMqtt {
|
||||||
mClient.subscribe(topic, qos);
|
mClient.subscribe(topic, qos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setConnectionCb(connectionCb cb) {
|
||||||
|
mConnectionCb = cb;
|
||||||
|
}
|
||||||
|
|
||||||
void setSubscriptionCb(subscriptionCb cb) {
|
void setSubscriptionCb(subscriptionCb cb) {
|
||||||
mSubscriptionCb = cb;
|
mSubscriptionCb = cb;
|
||||||
}
|
}
|
||||||
|
@ -268,6 +273,10 @@ class PubMqtt {
|
||||||
snprintf(mVal.data(), mVal.size(), "ctrl/#");
|
snprintf(mVal.data(), mVal.size(), "ctrl/#");
|
||||||
subscribe(mVal.data(), QOS_2);
|
subscribe(mVal.data(), QOS_2);
|
||||||
subscribe(subscr[MQTT_SUBS_SET_TIME]);
|
subscribe(subscr[MQTT_SUBS_SET_TIME]);
|
||||||
|
|
||||||
|
if(NULL == mConnectionCb)
|
||||||
|
return;
|
||||||
|
(mConnectionCb)();
|
||||||
}
|
}
|
||||||
|
|
||||||
void onDisconnect(espMqttClientTypes::DisconnectReason reason) {
|
void onDisconnect(espMqttClientTypes::DisconnectReason reason) {
|
||||||
|
@ -619,6 +628,7 @@ class PubMqtt {
|
||||||
uint32_t mRxCnt = 0, mTxCnt = 0;
|
uint32_t mRxCnt = 0, mTxCnt = 0;
|
||||||
std::queue<sendListCmdIv> mSendList;
|
std::queue<sendListCmdIv> mSendList;
|
||||||
std::array<bool, MAX_NUM_INVERTERS> mSendAlarm;
|
std::array<bool, MAX_NUM_INVERTERS> mSendAlarm;
|
||||||
|
connectionCb mConnectionCb = nullptr;
|
||||||
subscriptionCb mSubscriptionCb = nullptr;
|
subscriptionCb mSubscriptionCb = nullptr;
|
||||||
bool mLastAnyAvail = false;
|
bool mLastAnyAvail = false;
|
||||||
std::array<InverterStatus, MAX_NUM_INVERTERS> mLastIvState;
|
std::array<InverterStatus, MAX_NUM_INVERTERS> mLastIvState;
|
||||||
|
|
|
@ -1180,7 +1180,6 @@ class RestApi {
|
||||||
mConfig->plugin.zeroExport.groups[group].Ki = jsonIn[F("Ki")];
|
mConfig->plugin.zeroExport.groups[group].Ki = jsonIn[F("Ki")];
|
||||||
mConfig->plugin.zeroExport.groups[group].Kd = jsonIn[F("Kd")];
|
mConfig->plugin.zeroExport.groups[group].Kd = jsonIn[F("Kd")];
|
||||||
// Global
|
// Global
|
||||||
mConfig->plugin.zeroExport.groups[group].state = zeroExportState::INIT;
|
|
||||||
mApp->saveSettings(false); // without reboot
|
mApp->saveSettings(false); // without reboot
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue