mirror of
https://github.com/lumapu/ahoy.git
synced 2025-05-16 10:26:10 +02:00
0.8.7
* fix ESP8266 inverter settings #1226 * send radio statistics via MqTT #1227 * made night communication inverter depended * added option to prevent adding values of inverter to total values (MqTT only) #1199
This commit is contained in:
parent
a82777b2a1
commit
1bc3a0f06f
12 changed files with 223 additions and 161 deletions
|
@ -1,5 +1,11 @@
|
||||||
# Development Changes
|
# Development Changes
|
||||||
|
|
||||||
|
## 0.8.7 - 2023-11-13
|
||||||
|
* fix ESP8266 inverter settings #1226
|
||||||
|
* send radio statistics via MqTT #1227
|
||||||
|
* made night communication inverter depended
|
||||||
|
* added option to prevent adding values of inverter to total values (MqTT only) #1199
|
||||||
|
|
||||||
## 0.8.6 - 2023-11-12
|
## 0.8.6 - 2023-11-12
|
||||||
* merged PR #1225
|
* merged PR #1225
|
||||||
* improved heuristics (prevent update of statitistic during testing)
|
* improved heuristics (prevent update of statitistic during testing)
|
||||||
|
|
92
src/app.cpp
92
src/app.cpp
|
@ -4,9 +4,7 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
|
|
||||||
#include "app.h"
|
#include "app.h"
|
||||||
|
|
||||||
#include "utils/sun.h"
|
#include "utils/sun.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -239,43 +237,50 @@ void app::tickCalcSunrise(void) {
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void app::tickIVCommunication(void) {
|
void app::tickIVCommunication(void) {
|
||||||
mIVCommunicationOn = !mConfig->sun.disNightCom; // if sun.disNightCom is false, communication is always on
|
bool restartTick = false;
|
||||||
if (!mIVCommunicationOn) { // inverter communication only during the day
|
bool zeroValues = false;
|
||||||
uint32_t nxtTrig;
|
uint32_t nxtTrig = 0;
|
||||||
if (mTimestamp < (mSunrise - mConfig->sun.offsetSec)) { // current time is before communication start, set next trigger to communication start
|
|
||||||
nxtTrig = mSunrise - mConfig->sun.offsetSec;
|
Inverter<> *iv;
|
||||||
} else {
|
for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i ++) {
|
||||||
if (mTimestamp >= (mSunset + mConfig->sun.offsetSec)) { // current time is past communication stop, nothing to do. Next update will be done at midnight by tickCalcSunrise
|
iv = mSys.getInverterByPos(i);
|
||||||
nxtTrig = 0;
|
if(NULL == iv)
|
||||||
} else { // current time lies within communication start/stop time, set next trigger to communication stop
|
continue;
|
||||||
mIVCommunicationOn = true;
|
|
||||||
nxtTrig = mSunset + mConfig->sun.offsetSec;
|
iv->commEnabled = !iv->config->disNightCom; // if sun.disNightCom is false, communication is always on
|
||||||
|
if (!iv->commEnabled) { // inverter communication only during the day
|
||||||
|
if (mTimestamp < (mSunrise - mConfig->sun.offsetSec)) { // current time is before communication start, set next trigger to communication start
|
||||||
|
nxtTrig = mSunrise - mConfig->sun.offsetSec;
|
||||||
|
} else {
|
||||||
|
if (mTimestamp >= (mSunset + mConfig->sun.offsetSec)) { // current time is past communication stop, nothing to do. Next update will be done at midnight by tickCalcSunrise
|
||||||
|
nxtTrig = 0;
|
||||||
|
} else { // current time lies within communication start/stop time, set next trigger to communication stop
|
||||||
|
iv->commEnabled = true;
|
||||||
|
nxtTrig = mSunset + mConfig->sun.offsetSec;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (nxtTrig != 0)
|
||||||
|
restartTick = true;
|
||||||
}
|
}
|
||||||
if (nxtTrig != 0)
|
|
||||||
onceAt(std::bind(&app::tickIVCommunication, this), nxtTrig, "ivCom");
|
if ((!iv->commEnabled) && (mConfig->inst.rstValsCommStop))
|
||||||
|
zeroValues = true;
|
||||||
}
|
}
|
||||||
tickComm();
|
|
||||||
|
if(restartTick) // at least one inverter
|
||||||
|
onceAt(std::bind(&app::tickIVCommunication, this), nxtTrig, "ivCom");
|
||||||
|
|
||||||
|
if (zeroValues) // at least one inverter
|
||||||
|
once(std::bind(&app::tickZeroValues, this), mConfig->nrf.sendInterval, "tZero");
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void app::tickSun(void) {
|
void app::tickSun(void) {
|
||||||
// only used and enabled by MQTT (see setup())
|
// only used and enabled by MQTT (see setup())
|
||||||
if (!mMqtt.tickerSun(mSunrise, mSunset, mConfig->sun.offsetSec, mConfig->sun.disNightCom))
|
if (!mMqtt.tickerSun(mSunrise, mSunset, mConfig->sun.offsetSec))
|
||||||
once(std::bind(&app::tickSun, this), 1, "mqSun"); // MQTT not connected, retry
|
once(std::bind(&app::tickSun, this), 1, "mqSun"); // MQTT not connected, retry
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
void app::tickComm(void) {
|
|
||||||
if ((!mIVCommunicationOn) && (mConfig->inst.rstValsCommStop))
|
|
||||||
once(std::bind(&app::tickZeroValues, this), mConfig->nrf.sendInterval, "tZero");
|
|
||||||
|
|
||||||
if (mMqttEnabled) {
|
|
||||||
if (!mMqtt.tickerComm(!mIVCommunicationOn))
|
|
||||||
once(std::bind(&app::tickComm, this), 5, "mqCom"); // MQTT not connected, retry after 5s
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void app::tickZeroValues(void) {
|
void app::tickZeroValues(void) {
|
||||||
zeroIvValues(!CHECK_AVAIL, SKIP_YIELD_DAY);
|
zeroIvValues(!CHECK_AVAIL, SKIP_YIELD_DAY);
|
||||||
|
@ -325,22 +330,24 @@ void app::tickMidnight(void) {
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void app::tickSend(void) {
|
void app::tickSend(void) {
|
||||||
if(!mIVCommunicationOn) {
|
|
||||||
DPRINTLN(DBG_WARN, F("Time not set or it is night time, therefore no communication to the inverter!"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) {
|
for (uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) {
|
||||||
Inverter<> *iv = mSys.getInverterByPos(i);
|
Inverter<> *iv = mSys.getInverterByPos(i);
|
||||||
if(NULL != iv) {
|
if(NULL == iv)
|
||||||
if(iv->config->enabled) {
|
continue;
|
||||||
iv->tickSend([this, iv](uint8_t cmd, bool isDevControl) {
|
|
||||||
if(isDevControl)
|
if(iv->config->enabled) {
|
||||||
mCommunication.addImportant(iv, cmd);
|
if(!iv->commEnabled) {
|
||||||
else
|
DPRINT_IVID(DBG_INFO, iv->id);
|
||||||
mCommunication.add(iv, cmd);
|
DBGPRINTLN(F("no communication to the inverter (night time)"));
|
||||||
});
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iv->tickSend([this, iv](uint8_t cmd, bool isDevControl) {
|
||||||
|
if(isDevControl)
|
||||||
|
mCommunication.addImportant(iv, cmd);
|
||||||
|
else
|
||||||
|
mCommunication.add(iv, cmd);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -358,6 +365,8 @@ void app:: zeroIvValues(bool checkAvail, bool skipYieldDay) {
|
||||||
continue; // skip to next inverter
|
continue; // skip to next inverter
|
||||||
if (!iv->config->enabled)
|
if (!iv->config->enabled)
|
||||||
continue; // skip to next inverter
|
continue; // skip to next inverter
|
||||||
|
if (iv->commEnabled)
|
||||||
|
continue; // skip to next inverter
|
||||||
|
|
||||||
if (checkAvail) {
|
if (checkAvail) {
|
||||||
if (!iv->isAvailable())
|
if (!iv->isAvailable())
|
||||||
|
@ -415,7 +424,6 @@ void app::resetSystem(void) {
|
||||||
|
|
||||||
mSendLastIvId = 0;
|
mSendLastIvId = 0;
|
||||||
mShowRebootRequest = false;
|
mShowRebootRequest = false;
|
||||||
mIVCommunicationOn = true;
|
|
||||||
mSavePending = false;
|
mSavePending = false;
|
||||||
mSaveReboot = false;
|
mSaveReboot = false;
|
||||||
|
|
||||||
|
|
|
@ -307,7 +307,6 @@ class app : public IApp, public ah::Scheduler {
|
||||||
Communication mCommunication;
|
Communication mCommunication;
|
||||||
|
|
||||||
bool mShowRebootRequest;
|
bool mShowRebootRequest;
|
||||||
bool mIVCommunicationOn;
|
|
||||||
|
|
||||||
#if defined(ETHERNET)
|
#if defined(ETHERNET)
|
||||||
ahoyeth mEth;
|
ahoyeth mEth;
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
* https://arduino-esp8266.readthedocs.io/en/latest/filesystem.html#flash-layout
|
* https://arduino-esp8266.readthedocs.io/en/latest/filesystem.html#flash-layout
|
||||||
* */
|
* */
|
||||||
|
|
||||||
#define CONFIG_VERSION 1
|
#define CONFIG_VERSION 2
|
||||||
|
|
||||||
|
|
||||||
#define PROT_MASK_INDEX 0x0001
|
#define PROT_MASK_INDEX 0x0001
|
||||||
|
@ -110,7 +110,6 @@ typedef struct {
|
||||||
typedef struct {
|
typedef struct {
|
||||||
float lat;
|
float lat;
|
||||||
float lon;
|
float lon;
|
||||||
bool disNightCom; // disable night communication
|
|
||||||
uint16_t offsetSec;
|
uint16_t offsetSec;
|
||||||
} cfgSun_t;
|
} cfgSun_t;
|
||||||
|
|
||||||
|
@ -145,6 +144,8 @@ typedef struct {
|
||||||
char chName[6][MAX_NAME_LENGTH];
|
char chName[6][MAX_NAME_LENGTH];
|
||||||
uint8_t frequency;
|
uint8_t frequency;
|
||||||
uint8_t powerLevel;
|
uint8_t powerLevel;
|
||||||
|
bool disNightCom; // disable night communication
|
||||||
|
bool add2Total; // add values to total values - useful if one inverter is on battery to turn off
|
||||||
} cfgIv_t;
|
} cfgIv_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -420,7 +421,6 @@ class settings {
|
||||||
|
|
||||||
mCfg.sun.lat = 0.0;
|
mCfg.sun.lat = 0.0;
|
||||||
mCfg.sun.lon = 0.0;
|
mCfg.sun.lon = 0.0;
|
||||||
mCfg.sun.disNightCom = false;
|
|
||||||
mCfg.sun.offsetSec = 0;
|
mCfg.sun.offsetSec = 0;
|
||||||
|
|
||||||
mCfg.serial.interval = SERIAL_INTERVAL;
|
mCfg.serial.interval = SERIAL_INTERVAL;
|
||||||
|
@ -442,8 +442,10 @@ class settings {
|
||||||
mCfg.inst.yieldEffiency = 0.955f;
|
mCfg.inst.yieldEffiency = 0.955f;
|
||||||
|
|
||||||
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
|
||||||
mCfg.inst.iv[i].frequency = 0x12; // 863MHz (minimum allowed frequency)
|
mCfg.inst.iv[i].frequency = 0x12; // 863MHz (minimum allowed frequency)
|
||||||
|
mCfg.inst.iv[i].disNightCom = false;
|
||||||
|
mCfg.inst.iv[i].add2Total = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
mCfg.led.led0 = DEF_LED0;
|
mCfg.led.led0 = DEF_LED0;
|
||||||
|
@ -465,11 +467,15 @@ class settings {
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadAddedDefaults() {
|
void loadAddedDefaults() {
|
||||||
if(0 < mCfg.configVersion) {
|
for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) {
|
||||||
for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) {
|
if(mCfg.configVersion < 1) {
|
||||||
mCfg.inst.iv[i].powerLevel = 0xff; // impossible high value
|
mCfg.inst.iv[i].powerLevel = 0xff; // impossible high value
|
||||||
mCfg.inst.iv[i].frequency = 0x0; // 860MHz (backward compatibility)
|
mCfg.inst.iv[i].frequency = 0x0; // 860MHz (backward compatibility)
|
||||||
}
|
}
|
||||||
|
if(mCfg.configVersion < 2) {
|
||||||
|
mCfg.inst.iv[i].disNightCom = false;
|
||||||
|
mCfg.inst.iv[i].add2Total = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -601,12 +607,10 @@ class settings {
|
||||||
if(set) {
|
if(set) {
|
||||||
obj[F("lat")] = mCfg.sun.lat;
|
obj[F("lat")] = mCfg.sun.lat;
|
||||||
obj[F("lon")] = mCfg.sun.lon;
|
obj[F("lon")] = mCfg.sun.lon;
|
||||||
obj[F("dis")] = mCfg.sun.disNightCom;
|
|
||||||
obj[F("offs")] = mCfg.sun.offsetSec;
|
obj[F("offs")] = mCfg.sun.offsetSec;
|
||||||
} else {
|
} else {
|
||||||
getVal<float>(obj, F("lat"), &mCfg.sun.lat);
|
getVal<float>(obj, F("lat"), &mCfg.sun.lat);
|
||||||
getVal<float>(obj, F("lon"), &mCfg.sun.lon);
|
getVal<float>(obj, F("lon"), &mCfg.sun.lon);
|
||||||
getVal<bool>(obj, F("dis"), &mCfg.sun.disNightCom);
|
|
||||||
getVal<uint16_t>(obj, F("offs"), &mCfg.sun.offsetSec);
|
getVal<uint16_t>(obj, F("offs"), &mCfg.sun.offsetSec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -734,6 +738,8 @@ class settings {
|
||||||
obj[F("sn")] = cfg->serial.u64;
|
obj[F("sn")] = cfg->serial.u64;
|
||||||
obj[F("freq")] = cfg->frequency;
|
obj[F("freq")] = cfg->frequency;
|
||||||
obj[F("pa")] = cfg->powerLevel;
|
obj[F("pa")] = cfg->powerLevel;
|
||||||
|
obj[F("dis")] = cfg->disNightCom;
|
||||||
|
obj[F("add")] = cfg->add2Total;
|
||||||
for(uint8_t i = 0; i < 6; i++) {
|
for(uint8_t i = 0; i < 6; i++) {
|
||||||
obj[F("yield")][i] = cfg->yieldCor[i];
|
obj[F("yield")][i] = cfg->yieldCor[i];
|
||||||
obj[F("pwr")][i] = cfg->chMaxPwr[i];
|
obj[F("pwr")][i] = cfg->chMaxPwr[i];
|
||||||
|
@ -745,6 +751,8 @@ class settings {
|
||||||
getVal<uint64_t>(obj, F("sn"), &cfg->serial.u64);
|
getVal<uint64_t>(obj, F("sn"), &cfg->serial.u64);
|
||||||
getVal<uint8_t>(obj, F("freq"), &cfg->frequency);
|
getVal<uint8_t>(obj, F("freq"), &cfg->frequency);
|
||||||
getVal<uint8_t>(obj, F("pa"), &cfg->powerLevel);
|
getVal<uint8_t>(obj, F("pa"), &cfg->powerLevel);
|
||||||
|
getVal<bool>(obj, F("dis"), &cfg->disNightCom);
|
||||||
|
getVal<bool>(obj, F("add"), &cfg->add2Total);
|
||||||
uint8_t size = 4;
|
uint8_t size = 4;
|
||||||
if(obj.containsKey(F("pwr")))
|
if(obj.containsKey(F("pwr")))
|
||||||
size = obj[F("pwr")].size();
|
size = obj[F("pwr")].size();
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
#define VERSION_MAJOR 0
|
#define VERSION_MAJOR 0
|
||||||
#define VERSION_MINOR 8
|
#define VERSION_MINOR 8
|
||||||
#define VERSION_PATCH 5
|
#define VERSION_PATCH 7
|
||||||
|
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
|
@ -130,6 +130,7 @@ class Inverter {
|
||||||
int8_t txRfQuality[5]; // heuristics tx quality (check 'Heuristics.h')
|
int8_t txRfQuality[5]; // heuristics tx quality (check 'Heuristics.h')
|
||||||
uint8_t txRfChId; // RF TX channel id
|
uint8_t txRfChId; // RF TX channel id
|
||||||
uint8_t curCmtFreq; // current used CMT frequency, used to check if freq. was changed during runtime
|
uint8_t curCmtFreq; // current used CMT frequency, used to check if freq. was changed during runtime
|
||||||
|
bool commEnabled; // 'pause night communication' sets this field to false
|
||||||
|
|
||||||
static uint32_t *timestamp; // system timestamp
|
static uint32_t *timestamp; // system timestamp
|
||||||
static cfgInst_t *generalConfig; // general inverter configuration from setup
|
static cfgInst_t *generalConfig; // general inverter configuration from setup
|
||||||
|
@ -150,6 +151,7 @@ class Inverter {
|
||||||
alarmLastId = 0;
|
alarmLastId = 0;
|
||||||
rssi = -127;
|
rssi = -127;
|
||||||
radio = NULL;
|
radio = NULL;
|
||||||
|
commEnabled = true;
|
||||||
memset(&radioStatistics, 0, sizeof(statistics_t));
|
memset(&radioStatistics, 0, sizeof(statistics_t));
|
||||||
memset(txRfQuality, -6, 5);
|
memset(txRfQuality, -6, 5);
|
||||||
|
|
||||||
|
|
|
@ -134,7 +134,7 @@ class PubMqtt {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool tickerSun(uint32_t sunrise, uint32_t sunset, uint32_t offs, bool disNightCom) {
|
bool tickerSun(uint32_t sunrise, uint32_t sunset, uint32_t offs) {
|
||||||
if (!mClient.connected())
|
if (!mClient.connected())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -142,7 +142,16 @@ class PubMqtt {
|
||||||
publish(subtopics[MQTT_SUNSET], String(sunset).c_str(), true);
|
publish(subtopics[MQTT_SUNSET], String(sunset).c_str(), true);
|
||||||
publish(subtopics[MQTT_COMM_START], String(sunrise - offs).c_str(), true);
|
publish(subtopics[MQTT_COMM_START], String(sunrise - offs).c_str(), true);
|
||||||
publish(subtopics[MQTT_COMM_STOP], String(sunset + offs).c_str(), true);
|
publish(subtopics[MQTT_COMM_STOP], String(sunset + offs).c_str(), true);
|
||||||
publish(subtopics[MQTT_DIS_NIGHT_COMM], ((disNightCom) ? dict[STR_TRUE] : dict[STR_FALSE]), true);
|
|
||||||
|
Inverter<> *iv;
|
||||||
|
for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) {
|
||||||
|
iv = mSys->getInverterByPos(i);
|
||||||
|
if(NULL == iv)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "%s/dis_night_comm", iv->config->name);
|
||||||
|
publish(mSubTopic, ((iv->commEnabled) ? dict[STR_TRUE] : dict[STR_FALSE]), true);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,6 @@ enum {
|
||||||
MQTT_SUNSET,
|
MQTT_SUNSET,
|
||||||
MQTT_COMM_START,
|
MQTT_COMM_START,
|
||||||
MQTT_COMM_STOP,
|
MQTT_COMM_STOP,
|
||||||
MQTT_DIS_NIGHT_COMM,
|
|
||||||
MQTT_COMM_DISABLED,
|
MQTT_COMM_DISABLED,
|
||||||
MQTT_COMM_DIS_TS,
|
MQTT_COMM_DIS_TS,
|
||||||
MQTT_VERSION,
|
MQTT_VERSION,
|
||||||
|
@ -69,7 +68,6 @@ const char* const subtopics[] PROGMEM = {
|
||||||
"sunset",
|
"sunset",
|
||||||
"comm_start",
|
"comm_start",
|
||||||
"comm_stop",
|
"comm_stop",
|
||||||
"dis_night_comm",
|
|
||||||
"comm_disabled",
|
"comm_disabled",
|
||||||
"comm_dis_ts",
|
"comm_dis_ts",
|
||||||
"version",
|
"version",
|
||||||
|
|
|
@ -31,11 +31,11 @@ class PubMqttIvData {
|
||||||
memset(mIvLastRTRpub, 0, MAX_NUM_INVERTERS * sizeof(uint32_t));
|
memset(mIvLastRTRpub, 0, MAX_NUM_INVERTERS * sizeof(uint32_t));
|
||||||
mRTRDataHasBeenSent = false;
|
mRTRDataHasBeenSent = false;
|
||||||
|
|
||||||
mTable[IDLE] = &PubMqttIvData::stateIdle;
|
mTable[IDLE] = &PubMqttIvData::stateIdle;
|
||||||
mTable[START] = &PubMqttIvData::stateStart;
|
mTable[START] = &PubMqttIvData::stateStart;
|
||||||
mTable[FIND_NXT_IV] = &PubMqttIvData::stateFindNxtIv;
|
mTable[FIND_NXT_IV] = &PubMqttIvData::stateFindNxtIv;
|
||||||
mTable[SEND_DATA] = &PubMqttIvData::stateSend;
|
mTable[SEND_DATA] = &PubMqttIvData::stateSend;
|
||||||
mTable[SEND_TOTALS] = &PubMqttIvData::stateSendTotals;
|
mTable[SEND_TOTALS] = &PubMqttIvData::stateSendTotals;
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
|
@ -142,25 +142,27 @@ class PubMqttIvData {
|
||||||
// calculate total values for RealTimeRunData_Debug
|
// calculate total values for RealTimeRunData_Debug
|
||||||
if (CH0 == rec->assign[mPos].ch) {
|
if (CH0 == rec->assign[mPos].ch) {
|
||||||
if(mIv->status > InverterStatus::STARTING) {
|
if(mIv->status > InverterStatus::STARTING) {
|
||||||
mTotalFound = true;
|
if(mIv->config->add2Total) {
|
||||||
switch (rec->assign[mPos].fieldId) {
|
mTotalFound = true;
|
||||||
case FLD_PAC:
|
switch (rec->assign[mPos].fieldId) {
|
||||||
mTotal[0] += mIv->getValue(mPos, rec);
|
case FLD_PAC:
|
||||||
break;
|
mTotal[0] += mIv->getValue(mPos, rec);
|
||||||
case FLD_YT:
|
break;
|
||||||
mTotal[1] += mIv->getValue(mPos, rec);
|
case FLD_YT:
|
||||||
break;
|
mTotal[1] += mIv->getValue(mPos, rec);
|
||||||
case FLD_YD: {
|
break;
|
||||||
float val = mIv->getValue(mPos, rec);
|
case FLD_YD: {
|
||||||
if(0 == val) // inverter restarted during day
|
float val = mIv->getValue(mPos, rec);
|
||||||
mSendTotalYd = false;
|
if(0 == val) // inverter restarted during day
|
||||||
else
|
mSendTotalYd = false;
|
||||||
mTotal[2] += val;
|
else
|
||||||
break;
|
mTotal[2] += val;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FLD_PDC:
|
||||||
|
mTotal[3] += mIv->getValue(mPos, rec);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case FLD_PDC:
|
|
||||||
mTotal[3] += mIv->getValue(mPos, rec);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
mAllTotalFound = false;
|
mAllTotalFound = false;
|
||||||
|
@ -178,12 +180,25 @@ class PubMqttIvData {
|
||||||
mPublish(mSubTopic, mVal, retained, qos);
|
mPublish(mSubTopic, mVal, retained, qos);
|
||||||
}
|
}
|
||||||
mPos++;
|
mPos++;
|
||||||
} else
|
} else {
|
||||||
|
sendRadioStat(rec->length);
|
||||||
mState = FIND_NXT_IV;
|
mState = FIND_NXT_IV;
|
||||||
|
}
|
||||||
} else
|
} else
|
||||||
mState = FIND_NXT_IV;
|
mState = FIND_NXT_IV;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void sendRadioStat(uint8_t start) {
|
||||||
|
snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "%s/radio_stat", mIv->config->name);
|
||||||
|
snprintf(mVal, 100, "{\"tx\":%d,\"success\":%d,\"fail\":%d,\"no_answer\":%d,\"retransmits\":%d}",
|
||||||
|
mIv->radioStatistics.txCnt,
|
||||||
|
mIv->radioStatistics.rxSuccess,
|
||||||
|
mIv->radioStatistics.rxFail,
|
||||||
|
mIv->radioStatistics.rxFailNoAnser,
|
||||||
|
mIv->radioStatistics.retransmits);
|
||||||
|
mPublish(mSubTopic, mVal, false, QOS_0);
|
||||||
|
}
|
||||||
|
|
||||||
void stateSendTotals() {
|
void stateSendTotals() {
|
||||||
uint8_t fieldId;
|
uint8_t fieldId;
|
||||||
mRTRDataHasBeenSent = true;
|
mRTRDataHasBeenSent = true;
|
||||||
|
@ -221,7 +236,8 @@ class PubMqttIvData {
|
||||||
} else {
|
} else {
|
||||||
mSendList->pop();
|
mSendList->pop();
|
||||||
mZeroValues = false;
|
mZeroValues = false;
|
||||||
mState = START;
|
mPos = 0;
|
||||||
|
mState = IDLE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,7 +258,7 @@ class PubMqttIvData {
|
||||||
bool mRTRDataHasBeenSent;
|
bool mRTRDataHasBeenSent;
|
||||||
|
|
||||||
char mSubTopic[32 + MAX_NAME_LENGTH + 1];
|
char mSubTopic[32 + MAX_NAME_LENGTH + 1];
|
||||||
char mVal[40];
|
char mVal[100];
|
||||||
bool mZeroValues; // makes sure that yield day is sent even if no inverter is online
|
bool mZeroValues; // makes sure that yield day is sent even if no inverter is online
|
||||||
|
|
||||||
std::queue<sendListCmdIv> *mSendList;
|
std::queue<sendListCmdIv> *mSendList;
|
||||||
|
|
|
@ -339,27 +339,30 @@ class RestApi {
|
||||||
Inverter<> *iv;
|
Inverter<> *iv;
|
||||||
for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i ++) {
|
for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i ++) {
|
||||||
iv = mSys->getInverterByPos(i);
|
iv = mSys->getInverterByPos(i);
|
||||||
if(NULL != iv) {
|
if(NULL == iv)
|
||||||
JsonObject obj2 = invArr.createNestedObject();
|
continue;
|
||||||
obj2[F("enabled")] = (bool)iv->config->enabled;
|
|
||||||
obj2[F("id")] = i;
|
|
||||||
obj2[F("name")] = String(iv->config->name);
|
|
||||||
obj2[F("serial")] = String(iv->config->serial.u64, HEX);
|
|
||||||
obj2[F("channels")] = iv->channels;
|
|
||||||
obj2[F("freq")] = iv->config->frequency;
|
|
||||||
if(0xff == iv->config->powerLevel) {
|
|
||||||
if((IV_HMT == iv->ivGen) || (IV_HMS == iv->ivGen))
|
|
||||||
obj2[F("pa")] = 30; // 20dBm
|
|
||||||
else
|
|
||||||
obj2[F("pa")] = 1; // low
|
|
||||||
} else
|
|
||||||
obj2[F("pa")] = iv->config->powerLevel;
|
|
||||||
|
|
||||||
for(uint8_t j = 0; j < iv->channels; j ++) {
|
JsonObject obj2 = invArr.createNestedObject();
|
||||||
obj2[F("ch_yield_cor")][j] = (double)iv->config->yieldCor[j];
|
obj2[F("enabled")] = (bool)iv->config->enabled;
|
||||||
obj2[F("ch_name")][j] = iv->config->chName[j];
|
obj2[F("id")] = i;
|
||||||
obj2[F("ch_max_pwr")][j] = iv->config->chMaxPwr[j];
|
obj2[F("name")] = String(iv->config->name);
|
||||||
}
|
obj2[F("serial")] = String(iv->config->serial.u64, HEX);
|
||||||
|
obj2[F("channels")] = iv->channels;
|
||||||
|
obj2[F("freq")] = iv->config->frequency;
|
||||||
|
obj2[F("disnightcom")] = (bool)iv->config->disNightCom;
|
||||||
|
obj2[F("add2total")] = (bool)iv->config->add2Total;
|
||||||
|
if(0xff == iv->config->powerLevel) {
|
||||||
|
if((IV_HMT == iv->ivGen) || (IV_HMS == iv->ivGen))
|
||||||
|
obj2[F("pa")] = 30; // 20dBm
|
||||||
|
else
|
||||||
|
obj2[F("pa")] = 1; // low
|
||||||
|
} else
|
||||||
|
obj2[F("pa")] = iv->config->powerLevel;
|
||||||
|
|
||||||
|
for(uint8_t j = 0; j < iv->channels; j ++) {
|
||||||
|
obj2[F("ch_yield_cor")][j] = (double)iv->config->yieldCor[j];
|
||||||
|
obj2[F("ch_name")][j] = iv->config->chName[j];
|
||||||
|
obj2[F("ch_max_pwr")][j] = iv->config->chMaxPwr[j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
obj[F("interval")] = String(mConfig->nrf.sendInterval);
|
obj[F("interval")] = String(mConfig->nrf.sendInterval);
|
||||||
|
@ -501,7 +504,6 @@ class RestApi {
|
||||||
void getSun(JsonObject obj) {
|
void getSun(JsonObject obj) {
|
||||||
obj[F("lat")] = mConfig->sun.lat ? String(mConfig->sun.lat, 5) : "";
|
obj[F("lat")] = mConfig->sun.lat ? String(mConfig->sun.lat, 5) : "";
|
||||||
obj[F("lon")] = mConfig->sun.lat ? String(mConfig->sun.lon, 5) : "";
|
obj[F("lon")] = mConfig->sun.lat ? String(mConfig->sun.lon, 5) : "";
|
||||||
obj[F("disnightcom")] = mConfig->sun.disNightCom;
|
|
||||||
obj[F("offs")] = mConfig->sun.offsetSec;
|
obj[F("offs")] = mConfig->sun.offsetSec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -583,24 +585,28 @@ class RestApi {
|
||||||
obj[F("ts_sunrise")] = mApp->getSunrise();
|
obj[F("ts_sunrise")] = mApp->getSunrise();
|
||||||
obj[F("ts_sunset")] = mApp->getSunset();
|
obj[F("ts_sunset")] = mApp->getSunset();
|
||||||
obj[F("ts_offset")] = mConfig->sun.offsetSec;
|
obj[F("ts_offset")] = mConfig->sun.offsetSec;
|
||||||
obj[F("disNightComm")] = mConfig->sun.disNightCom;
|
|
||||||
|
|
||||||
JsonArray inv = obj.createNestedArray(F("inverter"));
|
JsonArray inv = obj.createNestedArray(F("inverter"));
|
||||||
Inverter<> *iv;
|
Inverter<> *iv;
|
||||||
|
bool disNightCom = false;
|
||||||
for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i ++) {
|
for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i ++) {
|
||||||
iv = mSys->getInverterByPos(i);
|
iv = mSys->getInverterByPos(i);
|
||||||
if(NULL != iv) {
|
if(NULL == iv)
|
||||||
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug);
|
continue;
|
||||||
JsonObject invObj = inv.createNestedObject();
|
|
||||||
invObj[F("enabled")] = (bool)iv->config->enabled;
|
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug);
|
||||||
invObj[F("id")] = i;
|
JsonObject invObj = inv.createNestedObject();
|
||||||
invObj[F("name")] = String(iv->config->name);
|
invObj[F("enabled")] = (bool)iv->config->enabled;
|
||||||
invObj[F("cur_pwr")] = ah::round3(iv->getChannelFieldValue(CH0, FLD_PAC, rec));
|
invObj[F("id")] = i;
|
||||||
invObj[F("is_avail")] = iv->isAvailable();
|
invObj[F("name")] = String(iv->config->name);
|
||||||
invObj[F("is_producing")] = iv->isProducing();
|
invObj[F("cur_pwr")] = ah::round3(iv->getChannelFieldValue(CH0, FLD_PAC, rec));
|
||||||
invObj[F("ts_last_success")] = iv->getLastTs(rec);
|
invObj[F("is_avail")] = iv->isAvailable();
|
||||||
}
|
invObj[F("is_producing")] = iv->isProducing();
|
||||||
|
invObj[F("ts_last_success")] = iv->getLastTs(rec);
|
||||||
|
if(iv->config->disNightCom)
|
||||||
|
disNightCom = true;
|
||||||
}
|
}
|
||||||
|
obj[F("disNightComm")] = disNightCom;
|
||||||
|
|
||||||
JsonArray warn = obj.createNestedArray(F("warnings"));
|
JsonArray warn = obj.createNestedArray(F("warnings"));
|
||||||
if(!mRadioNrf->isChipConnected() && mConfig->nrf.enabled)
|
if(!mRadioNrf->isChipConnected() && mConfig->nrf.enabled)
|
||||||
|
@ -729,8 +735,10 @@ class RestApi {
|
||||||
}
|
}
|
||||||
|
|
||||||
mApp->initInverter(jsonIn[F("id")]);
|
mApp->initInverter(jsonIn[F("id")]);
|
||||||
iv->config->frequency = jsonIn[F("freq")];
|
iv->config->frequency = jsonIn[F("freq")];
|
||||||
iv->config->powerLevel = jsonIn[F("pa")];
|
iv->config->powerLevel = jsonIn[F("pa")];
|
||||||
|
iv->config->disNightCom = jsonIn[F("disnightcom")];
|
||||||
|
iv->config->add2Total = jsonIn[F("add2total")];
|
||||||
mApp->saveSettings(false); // without reboot
|
mApp->saveSettings(false); // without reboot
|
||||||
} else {
|
} else {
|
||||||
jsonOut[F("error")] = F("unknown cmd");
|
jsonOut[F("error")] = F("unknown cmd");
|
||||||
|
|
|
@ -140,38 +140,33 @@
|
||||||
<fieldset class="mb-4">
|
<fieldset class="mb-4">
|
||||||
<legend class="des">Inverter</legend>
|
<legend class="des">Inverter</legend>
|
||||||
<div id="inverter"></div>
|
<div id="inverter"></div>
|
||||||
|
<div class="row mb-3">
|
||||||
<div class="row mb-2">
|
<div class="col-8 my-2">Interval [s]</div>
|
||||||
<div class="col-12 col-sm-3"><p class="subdes">General</p></div>
|
<div class="col-4"><input type="number" name="invInterval" title="Invalid input"/></div>
|
||||||
<div class="col-12 col-sm-9"></div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-3">
|
<div class="row mb-3">
|
||||||
<div class="col-12 col-sm-3 my-2">Interval [s]</div>
|
<div class="col-8 mb-2">Reset values and YieldDay at midnight</div>
|
||||||
<div class="col-12 col-sm-9"><input type="number" name="invInterval" title="Invalid input"/></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 col-sm-3 mb-2">Reset values and YieldDay at midnight</div>
|
<div class="col-8 mb-2">Reset values when inverter polling pauses at sunset</div>
|
||||||
<div class="col-4 col-sm-9"><input type="checkbox" name="invRstMid"/></div>
|
<div class="col-4"><input type="checkbox" name="invRstComStop"/></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-3">
|
<div class="row mb-3">
|
||||||
<div class="col-8 col-sm-3 mb-2">Reset values when inverter polling pauses at sunset</div>
|
<div class="col-8">Reset values when inverter status is 'not available'</div>
|
||||||
<div class="col-4 col-sm-9"><input type="checkbox" name="invRstComStop"/></div>
|
<div class="col-4"><input type="checkbox" name="invRstNotAvail"/></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-3">
|
<div class="row mb-3">
|
||||||
<div class="col-8 col-sm-3">Reset values when inverter status is 'not available'</div>
|
<div class="col-8">Reset 'max' values at midnight</div>
|
||||||
<div class="col-4 col-sm-9"><input type="checkbox" name="invRstNotAvail"/></div>
|
<div class="col-4"><input type="checkbox" name="invRstMaxMid"/></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-3">
|
<div class="row mb-3">
|
||||||
<div class="col-8 col-sm-3">Reset 'max' values at midnight</div>
|
<div class="col-8">Start without time sync (useful in AP-Only-Mode)</div>
|
||||||
<div class="col-4 col-sm-9"><input type="checkbox" name="invRstMaxMid"/></div>
|
<div class="col-4"><input type="checkbox" name="strtWthtTm"/></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-3">
|
<div class="row mb-3">
|
||||||
<div class="col-8 col-sm-3">Start without time sync (useful in AP-Only-Mode)</div>
|
<div class="col-8">Yield Efficiency (should be between 0.95 and 0.96)</div>
|
||||||
<div class="col-4 col-sm-9"><input type="checkbox" name="strtWthtTm"/></div>
|
<div class="col-4"><input type="number" name="yldEff" step="any"/></div>
|
||||||
</div>
|
|
||||||
<div class="row mb-3">
|
|
||||||
<div class="col-8 col-sm-3">Yield Efficiency (should be between 0.95 and 0.96)</div>
|
|
||||||
<div class="col-4 col-sm-9"><input type="number" name="yldEff" step="any"/></div>
|
|
||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
|
@ -223,10 +218,6 @@
|
||||||
<div class="col-12 col-sm-3 my-2">Offset (pre sunrise, post sunset)</div>
|
<div class="col-12 col-sm-3 my-2">Offset (pre sunrise, post sunset)</div>
|
||||||
<div class="col-12 col-sm-9"><select name="sunOffs"></select></div>
|
<div class="col-12 col-sm-9"><select name="sunOffs"></select></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-3">
|
|
||||||
<div class="col-8 col-sm-3">Pause polling inverters during night</div>
|
|
||||||
<div class="col-4 col-sm-9"><input type="checkbox" name="sunDisNightCom"/></div>
|
|
||||||
</div>
|
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -434,6 +425,7 @@
|
||||||
[47, "GPIO47"],
|
[47, "GPIO47"],
|
||||||
[48, "GPIO48"],
|
[48, "GPIO48"],
|
||||||
];
|
];
|
||||||
|
/*ENDIF_ESP32*/
|
||||||
var nrfPa = [
|
var nrfPa = [
|
||||||
[0, "MIN (recommended)"],
|
[0, "MIN (recommended)"],
|
||||||
[1, "LOW"],
|
[1, "LOW"],
|
||||||
|
@ -442,6 +434,8 @@
|
||||||
];
|
];
|
||||||
var esp32cmtPa = [];
|
var esp32cmtPa = [];
|
||||||
var esp32cmtFreq = [];
|
var esp32cmtFreq = [];
|
||||||
|
|
||||||
|
/*IF_ESP32*/
|
||||||
var freqFmt = new Intl.NumberFormat('en-US', {
|
var freqFmt = new Intl.NumberFormat('en-US', {
|
||||||
minimumIntegerDigits: 3,
|
minimumIntegerDigits: 3,
|
||||||
minimumFractionDigits: 2
|
minimumFractionDigits: 2
|
||||||
|
@ -645,6 +639,7 @@
|
||||||
add.ch_yield_cor = [];
|
add.ch_yield_cor = [];
|
||||||
add.freq = 12;
|
add.freq = 12;
|
||||||
add.pa = 30;
|
add.pa = 30;
|
||||||
|
add.add2total = true;
|
||||||
|
|
||||||
var e = document.getElementById("inverter");
|
var e = document.getElementById("inverter");
|
||||||
e.innerHTML = ""; // remove all childs
|
e.innerHTML = ""; // remove all childs
|
||||||
|
@ -674,23 +669,27 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
var cbEn = ml("input", {name: "enable", type: "checkbox"}, null);
|
var cbEn = ml("input", {name: "enable", type: "checkbox"}, null);
|
||||||
if(obj.enabled)
|
var cbDisNightCom = ml("input", {name: "disnightcom", type: "checkbox"}, null);
|
||||||
cbEn.checked = true;
|
var cbAddTotal = ml("input", {name: "add2total", type: "checkbox"}, null);
|
||||||
|
cbEn.checked = (obj.enabled);
|
||||||
|
cbDisNightCom.checked = (obj.disnightcom);
|
||||||
|
cbAddTotal.checked = (obj.add2total);
|
||||||
|
|
||||||
var ser = ml("input", {name: "ser", class: "text", type: "number", max: 138999999999, value: obj.serial}, null);
|
var ser = ml("input", {name: "ser", class: "text", type: "number", max: 138999999999, value: obj.serial}, null);
|
||||||
var html = ml("div", {}, [
|
var html = ml("div", {}, [
|
||||||
tabs(["General", "Inputs", "Radio"]),
|
tabs(["General", "Inputs", "Radio", "Advanced"]),
|
||||||
ml("div", {id: "divGeneral", class: "tab-content"}, [
|
ml("div", {id: "divGeneral", class: "tab-content"}, [
|
||||||
ml("div", {class: "row mb-3"}, [
|
ml("div", {class: "row mb-3"}, [
|
||||||
ml("div", {class: "col-4"}, "Enable"),
|
ml("div", {class: "col-2"}, "Enable"),
|
||||||
ml("div", {class: "col-8"}, cbEn)
|
ml("div", {class: "col-10"}, cbEn)
|
||||||
]),
|
]),
|
||||||
ml("div", {class: "row mb-3"}, [
|
ml("div", {class: "row mb-3"}, [
|
||||||
ml("div", {class: "col-4 mt-2"}, "Serial"),
|
ml("div", {class: "col-2 mt-2"}, "Serial"),
|
||||||
ml("div", {class: "col-8"}, ser)
|
ml("div", {class: "col-10"}, ser)
|
||||||
]),
|
]),
|
||||||
ml("div", {class: "row mb-3"}, [
|
ml("div", {class: "row mb-3"}, [
|
||||||
ml("div", {class: "col-4 mt-2"}, "Name"),
|
ml("div", {class: "col-2 mt-2"}, "Name"),
|
||||||
ml("div", {class: "col-8"}, ml("input", {name: "name", class: "text", type: "text", value: obj.name}, null))
|
ml("div", {class: "col-10"}, ml("input", {name: "name", class: "text", type: "text", value: obj.name}, null))
|
||||||
])
|
])
|
||||||
]),
|
]),
|
||||||
ml("div", {id: "divInputs", class: "tab-content hide"}, [
|
ml("div", {id: "divInputs", class: "tab-content hide"}, [
|
||||||
|
@ -704,21 +703,31 @@
|
||||||
ml("input", {type: "hidden", name: "isnrf"}, null),
|
ml("input", {type: "hidden", name: "isnrf"}, null),
|
||||||
ml("div", {id: "setcmt"}, [
|
ml("div", {id: "setcmt"}, [
|
||||||
ml("div", {class: "row mb-3"}, [
|
ml("div", {class: "row mb-3"}, [
|
||||||
ml("div", {class: "col-4 mt-2"}, "Frequency"),
|
ml("div", {class: "col-3 mt-2"}, "Frequency"),
|
||||||
ml("div", {class: "col-8"}, sel("freq", esp32cmtFreq, obj.freq))
|
ml("div", {class: "col-9"}, sel("freq", esp32cmtFreq, obj.freq))
|
||||||
]),
|
]),
|
||||||
ml("div", {class: "row mb-3"}, [
|
ml("div", {class: "row mb-3"}, [
|
||||||
ml("div", {class: "col-4 mt-2"}, "Power Level"),
|
ml("div", {class: "col-3 mt-2"}, "Power Level"),
|
||||||
ml("div", {class: "col-8"}, sel("cmtpa", esp32cmtPa, obj.pa))
|
ml("div", {class: "col-9"}, sel("cmtpa", esp32cmtPa, obj.pa))
|
||||||
]),
|
]),
|
||||||
]),
|
]),
|
||||||
ml("div", {id: "setnrf"},
|
ml("div", {id: "setnrf"},
|
||||||
ml("div", {class: "row mb-3"}, [
|
ml("div", {class: "row mb-3"}, [
|
||||||
ml("div", {class: "col-4 mt-2"}, "Power Level"),
|
ml("div", {class: "col-3 mt-2"}, "Power Level"),
|
||||||
ml("div", {class: "col-8"}, sel("nrfpa", nrfPa, obj.pa))
|
ml("div", {class: "col-9"}, sel("nrfpa", nrfPa, obj.pa))
|
||||||
]),
|
]),
|
||||||
),
|
),
|
||||||
]),
|
]),
|
||||||
|
ml("div", {id: "divAdvanced", class: "tab-content hide"}, [
|
||||||
|
ml("div", {class: "row mb-3"}, [
|
||||||
|
ml("div", {class: "col-10"}, "Pause communication during night (lat. and lon. need to be set)"),
|
||||||
|
ml("div", {class: "col-2"}, cbDisNightCom)
|
||||||
|
]),
|
||||||
|
ml("div", {class: "row mb-3"}, [
|
||||||
|
ml("div", {class: "col-10"}, "Include inverter to sum of total (should be checked by default)"),
|
||||||
|
ml("div", {class: "col-2"}, cbAddTotal)
|
||||||
|
])
|
||||||
|
]),
|
||||||
ml("div", {class: "row mt-5"}, [
|
ml("div", {class: "row mt-5"}, [
|
||||||
ml("div", {class: "col-8", id: "res"}, ""),
|
ml("div", {class: "col-8", id: "res"}, ""),
|
||||||
ml("div", {class: "col-4 a-r"}, ml("input", {type: "button", value: "save", class: "btn", onclick: function() { ivSave(); }}, null))
|
ml("div", {class: "col-4 a-r"}, ml("input", {type: "button", value: "save", class: "btn", onclick: function() { ivSave(); }}, null))
|
||||||
|
@ -758,7 +767,7 @@
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
modal("Edit inverter", html);
|
modal("Edit inverter " + obj.name, html);
|
||||||
ser.dispatchEvent(new Event('change'));
|
ser.dispatchEvent(new Event('change'));
|
||||||
|
|
||||||
function ivSave() {
|
function ivSave() {
|
||||||
|
@ -781,6 +790,8 @@
|
||||||
else
|
else
|
||||||
o.pa = document.getElementsByName("cmtpa")[0].value;
|
o.pa = document.getElementsByName("cmtpa")[0].value;
|
||||||
o.freq = document.getElementsByName("freq")[0].value;
|
o.freq = document.getElementsByName("freq")[0].value;
|
||||||
|
o.disnightcom = document.getElementsByName("disnightcom")[0].checked;
|
||||||
|
o.add2total = document.getElementsByName("add2total")[0].checked;
|
||||||
getAjax("/api/setup", cb, "POST", JSON.stringify(o));
|
getAjax("/api/setup", cb, "POST", JSON.stringify(o));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -841,7 +852,6 @@
|
||||||
function parseSun(obj) {
|
function parseSun(obj) {
|
||||||
document.getElementsByName("sunLat")[0].value = obj["lat"];
|
document.getElementsByName("sunLat")[0].value = obj["lat"];
|
||||||
document.getElementsByName("sunLon")[0].value = obj["lon"];
|
document.getElementsByName("sunLon")[0].value = obj["lon"];
|
||||||
document.getElementsByName("sunDisNightCom")[0].checked = obj["disnightcom"];
|
|
||||||
const sel = document.getElementsByName("sunOffs")[0];
|
const sel = document.getElementsByName("sunOffs")[0];
|
||||||
for(var i = 0; i <= 60; i++) {
|
for(var i = 0; i <= 60; i++) {
|
||||||
sel.appendChild(opt(i, i + " minutes", (i == (obj["offs"] / 60))));
|
sel.appendChild(opt(i, i + " minutes", (i == (obj["offs"] / 60))));
|
||||||
|
|
|
@ -535,12 +535,10 @@ class Web {
|
||||||
if (request->arg("sunLat") == "" || (request->arg("sunLon") == "")) {
|
if (request->arg("sunLat") == "" || (request->arg("sunLon") == "")) {
|
||||||
mConfig->sun.lat = 0.0;
|
mConfig->sun.lat = 0.0;
|
||||||
mConfig->sun.lon = 0.0;
|
mConfig->sun.lon = 0.0;
|
||||||
mConfig->sun.disNightCom = false;
|
|
||||||
mConfig->sun.offsetSec = 0;
|
mConfig->sun.offsetSec = 0;
|
||||||
} else {
|
} else {
|
||||||
mConfig->sun.lat = request->arg("sunLat").toFloat();
|
mConfig->sun.lat = request->arg("sunLat").toFloat();
|
||||||
mConfig->sun.lon = request->arg("sunLon").toFloat();
|
mConfig->sun.lon = request->arg("sunLon").toFloat();
|
||||||
mConfig->sun.disNightCom = (request->arg("sunDisNightCom") == "on");
|
|
||||||
mConfig->sun.offsetSec = request->arg("sunOffs").toInt() * 60;
|
mConfig->sun.offsetSec = request->arg("sunOffs").toInt() * 60;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue