mirror of
https://github.com/lumapu/ahoy.git
synced 2025-05-30 09:16:11 +02:00
Merge branch 'lumapu:development03' into development03
This commit is contained in:
commit
b942b37cfd
22 changed files with 990 additions and 61 deletions
2
.github/workflows/compile_development.yml
vendored
2
.github/workflows/compile_development.yml
vendored
|
@ -43,7 +43,7 @@ jobs:
|
||||||
pip install --upgrade platformio
|
pip install --upgrade platformio
|
||||||
|
|
||||||
- name: Run PlatformIO
|
- name: Run PlatformIO
|
||||||
run: pio run -d src --environment esp8266 --environment esp8266-prometheus --environment esp8285 --environment esp32-wroom32 --environment esp32-wroom32-prometheus --environment esp32-wroom32-ethernet --environment esp32-s2-mini --environment opendtufusion --environment opendtufusion-ethernet
|
run: pio run -d src --environment esp8266 --environment esp8266-prometheus --environment esp8285 --environment esp32-wroom32 --environment esp32-wroom32-prometheus --environment esp32-wroom32-ethernet --environment esp32-s2-mini --environment esp32-c3-mini --environment opendtufusion --environment opendtufusion-ethernet
|
||||||
|
|
||||||
- name: Copy boot_app0.bin
|
- name: Copy boot_app0.bin
|
||||||
run: cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin src/.pio/build/opendtufusion/ota.bin
|
run: cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin src/.pio/build/opendtufusion/ota.bin
|
||||||
|
|
2
.github/workflows/compile_release.yml
vendored
2
.github/workflows/compile_release.yml
vendored
|
@ -47,7 +47,7 @@ jobs:
|
||||||
pip install --upgrade platformio
|
pip install --upgrade platformio
|
||||||
|
|
||||||
- name: Run PlatformIO
|
- name: Run PlatformIO
|
||||||
run: pio run -d src --environment esp8266 --environment esp8266-prometheus --environment esp8285 --environment esp32-wroom32 --environment esp32-wroom32-prometheus --environment esp32-wroom32-ethernet --environment esp32-s2-mini --environment opendtufusion --environment opendtufusion-ethernet
|
run: pio run -d src --environment esp8266 --environment esp8266-prometheus --environment esp8285 --environment esp32-wroom32 --environment esp32-wroom32-prometheus --environment esp32-wroom32-ethernet --environment esp32-s2-mini --environment esp32-c3-mini --environment opendtufusion --environment opendtufusion-ethernet
|
||||||
|
|
||||||
- name: Copy boot_app0.bin
|
- name: Copy boot_app0.bin
|
||||||
run: cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin src/.pio/build/opendtufusion/ota.bin
|
run: cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin src/.pio/build/opendtufusion/ota.bin
|
||||||
|
|
|
@ -1,3 +1,16 @@
|
||||||
|
diff --git a/src/AsyncWebSocket.cpp b/src/AsyncWebSocket.cpp
|
||||||
|
index 12be5f8..cffeed7 100644
|
||||||
|
--- a/src/AsyncWebSocket.cpp
|
||||||
|
+++ b/src/AsyncWebSocket.cpp
|
||||||
|
@@ -737,7 +737,7 @@ void AsyncWebSocketClient::binary(const __FlashStringHelper *data, size_t len)
|
||||||
|
IPAddress AsyncWebSocketClient::remoteIP() const
|
||||||
|
{
|
||||||
|
if (!_client)
|
||||||
|
- return IPAddress(0U);
|
||||||
|
+ return IPAddress();
|
||||||
|
|
||||||
|
return _client->remoteIP();
|
||||||
|
}
|
||||||
diff --git a/src/WebResponses.cpp b/src/WebResponses.cpp
|
diff --git a/src/WebResponses.cpp b/src/WebResponses.cpp
|
||||||
index 22a549f..e0b36b3 100644
|
index 22a549f..e0b36b3 100644
|
||||||
--- a/src/WebResponses.cpp
|
--- a/src/WebResponses.cpp
|
||||||
|
|
|
@ -159,7 +159,7 @@ if os.path.exists(wd):
|
||||||
|
|
||||||
# grab all files with following extensions
|
# grab all files with following extensions
|
||||||
os.chdir('./web/html')
|
os.chdir('./web/html')
|
||||||
types = ('*.html', '*.css', '*.js', '*.ico') # the tuple of file types
|
types = ('*.html', '*.css', '*.js', '*.ico', '*.json') # the tuple of file types
|
||||||
files_grabbed = []
|
files_grabbed = []
|
||||||
for files in types:
|
for files in types:
|
||||||
files_grabbed.extend(glob.glob(files))
|
files_grabbed.extend(glob.glob(files))
|
||||||
|
|
|
@ -55,6 +55,7 @@ def readVersion(path, infile):
|
||||||
os.mkdir(path + "firmware/ESP32/")
|
os.mkdir(path + "firmware/ESP32/")
|
||||||
os.mkdir(path + "firmware/ESP32-S2/")
|
os.mkdir(path + "firmware/ESP32-S2/")
|
||||||
os.mkdir(path + "firmware/ESP32-S3/")
|
os.mkdir(path + "firmware/ESP32-S3/")
|
||||||
|
os.mkdir(path + "firmware/ESP32-C3/")
|
||||||
os.mkdir(path + "firmware/ESP32-S3-ETH/")
|
os.mkdir(path + "firmware/ESP32-S3-ETH/")
|
||||||
sha = os.getenv("SHA",default="sha")
|
sha = os.getenv("SHA",default="sha")
|
||||||
|
|
||||||
|
@ -94,6 +95,11 @@ def readVersion(path, infile):
|
||||||
dst = path + "firmware/ESP32-S2/" + versionout
|
dst = path + "firmware/ESP32-S2/" + versionout
|
||||||
os.rename(src, dst)
|
os.rename(src, dst)
|
||||||
|
|
||||||
|
versionout = version[:-1] + "_" + sha + "_esp32c3-mini.bin"
|
||||||
|
src = path + ".pio/build/esp32-c3-mini/firmware.bin"
|
||||||
|
dst = path + "firmware/ESP32-C3/" + versionout
|
||||||
|
os.rename(src, dst)
|
||||||
|
|
||||||
versionout = version[:-1] + "_" + sha + "_esp32s3.bin"
|
versionout = version[:-1] + "_" + sha + "_esp32s3.bin"
|
||||||
src = path + ".pio/build/opendtufusion/firmware.bin"
|
src = path + ".pio/build/opendtufusion/firmware.bin"
|
||||||
dst = path + "firmware/ESP32-S3/" + versionout
|
dst = path + "firmware/ESP32-S3/" + versionout
|
||||||
|
@ -118,6 +124,13 @@ def readVersion(path, infile):
|
||||||
os.rename(src + "partitions.bin", dst + "partitions.bin")
|
os.rename(src + "partitions.bin", dst + "partitions.bin")
|
||||||
genOtaBin(dst)
|
genOtaBin(dst)
|
||||||
|
|
||||||
|
# other ESP32-C3 bin files
|
||||||
|
src = path + ".pio/build/esp32-c3-mini/"
|
||||||
|
dst = path + "firmware/ESP32-C3/"
|
||||||
|
os.rename(src + "bootloader.bin", dst + "bootloader.bin")
|
||||||
|
os.rename(src + "partitions.bin", dst + "partitions.bin")
|
||||||
|
genOtaBin(dst)
|
||||||
|
|
||||||
# other ESP32-S3 bin files
|
# other ESP32-S3 bin files
|
||||||
src = path + ".pio/build/opendtufusion/"
|
src = path + ".pio/build/opendtufusion/"
|
||||||
dst = path + "firmware/ESP32-S3/"
|
dst = path + "firmware/ESP32-S3/"
|
||||||
|
|
|
@ -1,5 +1,14 @@
|
||||||
# Development Changes
|
# Development Changes
|
||||||
|
|
||||||
|
## 0.8.29 - 2023-12-27
|
||||||
|
* fix MqTT generic topic `comm_disabled` #1265 #1286
|
||||||
|
* potential fix of #1285 (reset yield day)
|
||||||
|
* fix fraction of yield correction #1280
|
||||||
|
* fix crash if `getLossRate` was read from inverter #1288 #1290
|
||||||
|
* reduce reload time for opendtufusion ethernet variant to 5 seconds
|
||||||
|
* added basic grid parser
|
||||||
|
* added ESP32-C3 mini environment #1289
|
||||||
|
|
||||||
## 0.8.28 - 2023-12-23
|
## 0.8.28 - 2023-12-23
|
||||||
* fix bug heuristic
|
* fix bug heuristic
|
||||||
* add version information to clipboard once 'copy' was clicked
|
* add version information to clipboard once 'copy' was clicked
|
||||||
|
|
|
@ -305,7 +305,7 @@ void app::tickMidnight(void) {
|
||||||
continue; // skip to next inverter
|
continue; // skip to next inverter
|
||||||
|
|
||||||
// reset alarms
|
// reset alarms
|
||||||
if(InverterStatus::OFF == iv->status)
|
if(InverterStatus::OFF == iv->getStatus())
|
||||||
iv->resetAlarms();
|
iv->resetAlarms();
|
||||||
|
|
||||||
// clear max values
|
// clear max values
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
#define VERSION_MAJOR 0
|
#define VERSION_MAJOR 0
|
||||||
#define VERSION_MINOR 8
|
#define VERSION_MINOR 8
|
||||||
#define VERSION_PATCH 28
|
#define VERSION_PATCH 29
|
||||||
|
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
|
@ -117,28 +117,6 @@ class Communication : public CommQueue<> {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case States::WAIT:
|
case States::WAIT:
|
||||||
/*if(millis() > mWaitTimeout_min) {
|
|
||||||
if(mIsRetransmit) { // we already have been through...
|
|
||||||
mWaitTimeout = mWaitTimeout_min;
|
|
||||||
} else if(q->iv->mGotFragment) { // nothing received yet?
|
|
||||||
if(q->iv->mGotLastMsg) {
|
|
||||||
//mState = States::CHECK_FRAMES;
|
|
||||||
mWaitTimeout = mWaitTimeout_min;
|
|
||||||
}
|
|
||||||
} else if(mFirstTry) {
|
|
||||||
if(*mSerialDebug) {
|
|
||||||
DPRINT_IVID(DBG_INFO, q->iv->id);
|
|
||||||
DBGPRINT(String(millis() - mWaitTimeout_min + mlastTO_min));
|
|
||||||
DBGPRINTLN(F("ms - second try"));
|
|
||||||
}
|
|
||||||
mFirstTry = false;
|
|
||||||
mlastTO_min = timeout_min;
|
|
||||||
q->iv->radioStatistics.retransmits++; // got nothing
|
|
||||||
mState = States::START;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}*/
|
|
||||||
if(millis() < mWaitTimeout)
|
if(millis() < mWaitTimeout)
|
||||||
return;
|
return;
|
||||||
mState = States::CHECK_FRAMES;
|
mState = States::CHECK_FRAMES;
|
||||||
|
@ -187,7 +165,7 @@ class Communication : public CommQueue<> {
|
||||||
if(parseMiFrame(p, q))
|
if(parseMiFrame(p, q))
|
||||||
q->iv->curFrmCnt++;
|
q->iv->curFrmCnt++;
|
||||||
}
|
}
|
||||||
} //else // serial does not match
|
} //else -> serial does not match
|
||||||
|
|
||||||
q->iv->radio->mBufCtrl.pop();
|
q->iv->radio->mBufCtrl.pop();
|
||||||
yield();
|
yield();
|
||||||
|
@ -221,7 +199,6 @@ class Communication : public CommQueue<> {
|
||||||
else
|
else
|
||||||
closeRequest(q, true);
|
closeRequest(q, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,7 +283,7 @@ class Communication : public CommQueue<> {
|
||||||
else
|
else
|
||||||
ah::dumpBuf(p->packet, p->len);
|
ah::dumpBuf(p->packet, p->len);
|
||||||
} else {
|
} else {
|
||||||
DBGPRINT(F("| 0x"));
|
DBGPRINT(F("| "));
|
||||||
DHEX(p->packet[0]);
|
DHEX(p->packet[0]);
|
||||||
DBGPRINT(F(" "));
|
DBGPRINT(F(" "));
|
||||||
DBGHEXLN(p->packet[9]);
|
DBGHEXLN(p->packet[9]);
|
||||||
|
|
|
@ -458,6 +458,11 @@ class Inverter {
|
||||||
return producing;
|
return producing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
InverterStatus getStatus(){
|
||||||
|
isProducing(); // recalculate status
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
uint16_t getFwVersion() {
|
uint16_t getFwVersion() {
|
||||||
record_t<> *rec = getRecordStruct(InverterDevInform_All);
|
record_t<> *rec = getRecordStruct(InverterDevInform_All);
|
||||||
return getChannelFieldValue(CH0, FLD_FW_VERSION, rec);
|
return getChannelFieldValue(CH0, FLD_FW_VERSION, rec);
|
||||||
|
|
|
@ -98,7 +98,7 @@ class HmRadio : public Radio {
|
||||||
if(mNrf24->isChipConnected()) {
|
if(mNrf24->isChipConnected()) {
|
||||||
DPRINTLN(DBG_INFO, F("Radio Config:"));
|
DPRINTLN(DBG_INFO, F("Radio Config:"));
|
||||||
mNrf24->printPrettyDetails();
|
mNrf24->printPrettyDetails();
|
||||||
DPRINT(DBG_INFO, F("DTU_SN: 0x"));
|
DPRINT(DBG_INFO, F("DTU_SN: "));
|
||||||
DBGPRINTLN(String(mDtuSn, HEX));
|
DBGPRINTLN(String(mDtuSn, HEX));
|
||||||
} else
|
} else
|
||||||
DPRINTLN(DBG_WARN, F("WARNING! your NRF24 module can't be reached, check the wiring"));
|
DPRINTLN(DBG_WARN, F("WARNING! your NRF24 module can't be reached, check the wiring"));
|
||||||
|
@ -152,7 +152,7 @@ class HmRadio : public Radio {
|
||||||
|
|
||||||
void sendControlPacket(Inverter<> *iv, uint8_t cmd, uint16_t *data, bool isRetransmit) {
|
void sendControlPacket(Inverter<> *iv, uint8_t cmd, uint16_t *data, bool isRetransmit) {
|
||||||
DPRINT_IVID(DBG_INFO, iv->id);
|
DPRINT_IVID(DBG_INFO, iv->id);
|
||||||
DBGPRINT(F("sendControlPacket cmd: 0x"));
|
DBGPRINT(F("sendControlPacket cmd: "));
|
||||||
DBGHEXLN(cmd);
|
DBGHEXLN(cmd);
|
||||||
initPacket(iv->radioId.u64, TX_REQ_DEVCONTROL, SINGLE_FRAME);
|
initPacket(iv->radioId.u64, TX_REQ_DEVCONTROL, SINGLE_FRAME);
|
||||||
uint8_t cnt = 10;
|
uint8_t cnt = 10;
|
||||||
|
@ -307,9 +307,8 @@ class HmRadio : public Radio {
|
||||||
else
|
else
|
||||||
ah::dumpBuf(mTxBuf, len);
|
ah::dumpBuf(mTxBuf, len);
|
||||||
} else {
|
} else {
|
||||||
DBGPRINT(F("0x"));
|
|
||||||
DHEX(mTxBuf[0]);
|
DHEX(mTxBuf[0]);
|
||||||
DBGPRINT(F(" 0x"));
|
DBGPRINT(F(" "));
|
||||||
DHEX(mTxBuf[10]);
|
DHEX(mTxBuf[10]);
|
||||||
DBGPRINT(F(" "));
|
DBGPRINT(F(" "));
|
||||||
DBGHEXLN(mTxBuf[9]);
|
DBGHEXLN(mTxBuf[9]);
|
||||||
|
|
|
@ -42,7 +42,7 @@ class CmtRadio : public Radio {
|
||||||
}
|
}
|
||||||
|
|
||||||
void sendControlPacket(Inverter<> *iv, uint8_t cmd, uint16_t *data, bool isRetransmit) {
|
void sendControlPacket(Inverter<> *iv, uint8_t cmd, uint16_t *data, bool isRetransmit) {
|
||||||
DPRINT(DBG_INFO, F("sendControlPacket cmd: 0x"));
|
DPRINT(DBG_INFO, F("sendControlPacket cmd: "));
|
||||||
DBGHEXLN(cmd);
|
DBGHEXLN(cmd);
|
||||||
initPacket(iv->radioId.u64, TX_REQ_DEVCONTROL, SINGLE_FRAME);
|
initPacket(iv->radioId.u64, TX_REQ_DEVCONTROL, SINGLE_FRAME);
|
||||||
uint8_t cnt = 10;
|
uint8_t cnt = 10;
|
||||||
|
@ -96,9 +96,8 @@ class CmtRadio : public Radio {
|
||||||
else
|
else
|
||||||
ah::dumpBuf(mTxBuf, len);
|
ah::dumpBuf(mTxBuf, len);
|
||||||
} else {
|
} else {
|
||||||
DBGPRINT(F("0x"));
|
|
||||||
DHEX(mTxBuf[0]);
|
DHEX(mTxBuf[0]);
|
||||||
DBGPRINT(F(" 0x"));
|
DBGPRINT(F(" "));
|
||||||
DHEX(mTxBuf[10]);
|
DHEX(mTxBuf[10]);
|
||||||
DBGHEXLN(mTxBuf[9]);
|
DBGHEXLN(mTxBuf[9]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,6 +123,21 @@ build_flags = ${env.build_flags}
|
||||||
monitor_filters =
|
monitor_filters =
|
||||||
esp32_exception_decoder
|
esp32_exception_decoder
|
||||||
|
|
||||||
|
[env:esp32-c3-mini]
|
||||||
|
platform = espressif32@6.4.0
|
||||||
|
board = lolin_c3_mini
|
||||||
|
build_flags = ${env.build_flags}
|
||||||
|
-DUSE_HSPI_FOR_EPD
|
||||||
|
-DDEF_NRF_CS_PIN=5
|
||||||
|
-DDEF_NRF_CE_PIN=0
|
||||||
|
-DDEF_NRF_IRQ_PIN=1
|
||||||
|
-DDEF_NRF_MISO_PIN=3
|
||||||
|
-DDEF_NRF_MOSI_PIN=4
|
||||||
|
-DDEF_NRF_SCLK_PIN=2
|
||||||
|
monitor_filters =
|
||||||
|
esp32_exception_decoder
|
||||||
|
|
||||||
|
|
||||||
[env:opendtufusion]
|
[env:opendtufusion]
|
||||||
platform = espressif32@6.4.0
|
platform = espressif32@6.4.0
|
||||||
board = esp32-s3-devkitc-1
|
board = esp32-s3-devkitc-1
|
||||||
|
|
|
@ -153,6 +153,10 @@ class PubMqtt {
|
||||||
publish(mSubTopic, ((iv->commEnabled) ? dict[STR_TRUE] : dict[STR_FALSE]), true);
|
publish(mSubTopic, ((iv->commEnabled) ? dict[STR_TRUE] : dict[STR_FALSE]), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "comm_disabled");
|
||||||
|
publish(mSubTopic, (((*mUtcTimestamp > (sunset + offs)) || (*mUtcTimestamp < (sunrise - offs))) ? dict[STR_TRUE] : dict[STR_FALSE]), true);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -483,22 +487,22 @@ class PubMqtt {
|
||||||
continue; // skip to next inverter
|
continue; // skip to next inverter
|
||||||
|
|
||||||
// inverter status
|
// inverter status
|
||||||
iv->isProducing(); // recalculate status
|
InverterStatus status = iv->getStatus();
|
||||||
if (InverterStatus::OFF < iv->status)
|
if (InverterStatus::OFF < status)
|
||||||
anyAvail = true;
|
anyAvail = true;
|
||||||
else // inverter is enabled but not available
|
else // inverter is enabled but not available
|
||||||
allAvail = false;
|
allAvail = false;
|
||||||
|
|
||||||
if(mLastIvState[id] != iv->status) {
|
if(mLastIvState[id] != status) {
|
||||||
// if status changed from producing to not producing send last data immediately
|
// if status changed from producing to not producing send last data immediately
|
||||||
if (InverterStatus::WAS_PRODUCING == mLastIvState[id])
|
if (InverterStatus::WAS_PRODUCING == mLastIvState[id])
|
||||||
sendData(iv, RealTimeRunData_Debug);
|
sendData(iv, RealTimeRunData_Debug);
|
||||||
|
|
||||||
mLastIvState[id] = iv->status;
|
mLastIvState[id] = status;
|
||||||
changed = true;
|
changed = true;
|
||||||
|
|
||||||
snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "%s/available", iv->config->name);
|
snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "%s/available", iv->config->name);
|
||||||
snprintf(mVal, 40, "%d", (uint8_t)iv->status);
|
snprintf(mVal, 40, "%d", (uint8_t)status);
|
||||||
publish(mSubTopic, mVal, true);
|
publish(mSubTopic, mVal, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -146,7 +146,7 @@ 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->getStatus() > InverterStatus::STARTING) {
|
||||||
if(mIv->config->add2Total) {
|
if(mIv->config->add2Total) {
|
||||||
mTotalFound = true;
|
mTotalFound = true;
|
||||||
switch (rec->assign[mPos].fieldId) {
|
switch (rec->assign[mPos].fieldId) {
|
||||||
|
|
|
@ -323,9 +323,14 @@ class RestApi {
|
||||||
|
|
||||||
void getHtmlSave(AsyncWebServerRequest *request, JsonObject obj) {
|
void getHtmlSave(AsyncWebServerRequest *request, JsonObject obj) {
|
||||||
getGeneric(request, obj.createNestedObject(F("generic")));
|
getGeneric(request, obj.createNestedObject(F("generic")));
|
||||||
obj["pending"] = (bool)mApp->getSavePending();
|
obj[F("pending")] = (bool)mApp->getSavePending();
|
||||||
obj["success"] = (bool)mApp->getLastSaveSucceed();
|
obj[F("success")] = (bool)mApp->getLastSaveSucceed();
|
||||||
obj["reboot"] = (bool)mApp->getShouldReboot();
|
obj[F("reboot")] = (bool)mApp->getShouldReboot();
|
||||||
|
#if defined(ETHERNET) && defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||||
|
obj[F("reload")] = 5;
|
||||||
|
#else
|
||||||
|
obj[F("reload")] = 20;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void getReboot(AsyncWebServerRequest *request, JsonObject obj) {
|
void getReboot(AsyncWebServerRequest *request, JsonObject obj) {
|
||||||
|
@ -421,7 +426,7 @@ class RestApi {
|
||||||
obj[F("max_pwr")] = iv->getMaxPower();
|
obj[F("max_pwr")] = iv->getMaxPower();
|
||||||
obj[F("ts_last_success")] = rec->ts;
|
obj[F("ts_last_success")] = rec->ts;
|
||||||
obj[F("generation")] = iv->ivGen;
|
obj[F("generation")] = iv->ivGen;
|
||||||
obj[F("status")] = (uint8_t)iv->status;
|
obj[F("status")] = (uint8_t)iv->getStatus();
|
||||||
obj[F("alarm_cnt")] = iv->alarmCnt;
|
obj[F("alarm_cnt")] = iv->alarmCnt;
|
||||||
obj[F("rssi")] = iv->rssi;
|
obj[F("rssi")] = iv->rssi;
|
||||||
|
|
||||||
|
|
|
@ -175,6 +175,14 @@ function getAjax(url, ptr, method="GET", json=null) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getJSON = async url => {
|
||||||
|
const re = await fetch(url);
|
||||||
|
if(!re.ok)
|
||||||
|
throw new Error(re.statusText);
|
||||||
|
const data = re.json();
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CREATE DOM FUNCTIONS
|
* CREATE DOM FUNCTIONS
|
||||||
*/
|
*/
|
||||||
|
|
764
src/web/html/grid_info.json
Normal file
764
src/web/html/grid_info.json
Normal file
|
@ -0,0 +1,764 @@
|
||||||
|
{
|
||||||
|
"type": [
|
||||||
|
{"0x0300": "DE_VDE4105_2018"},
|
||||||
|
{"0x0a00": "DE NF_EN_50549-1:2019"},
|
||||||
|
{"0x0c00": "AT_TOR_Erzeuger_default"},
|
||||||
|
{"0x0d04": "France NF_EN_50549-1:2019"},
|
||||||
|
{"0x1200": "2.0.4 (EU_EN50438)"},
|
||||||
|
{"0x3700": "2.0.0 (CH_NA EEA-NE7–CH2020)"}
|
||||||
|
],
|
||||||
|
"grp_codes": [
|
||||||
|
{"0x00": "Voltage H/LVRT"},
|
||||||
|
{"0x10": "Frequency H/LFRT"},
|
||||||
|
{"0x20": "Islanding Detection"},
|
||||||
|
{"0x30": "Reconnection"},
|
||||||
|
{"0x40": "Ramp Rates"},
|
||||||
|
{"0x50": "Frequency Watt"},
|
||||||
|
{"0x60": "Volt Watt"},
|
||||||
|
{"0x70": "Active Power Control"},
|
||||||
|
{"0x80": "Volt Var"},
|
||||||
|
{"0x90": "Specified Power Factor"},
|
||||||
|
{"0xa0": "Reactive Power Control"},
|
||||||
|
{"0xb0": "Watt Power Factor"}
|
||||||
|
],
|
||||||
|
"group": [
|
||||||
|
{
|
||||||
|
"0x0003": [
|
||||||
|
{
|
||||||
|
"name": "Nominal Voltage",
|
||||||
|
"div": 10,
|
||||||
|
"def": 230,
|
||||||
|
"unit": "V"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Low Voltage 1",
|
||||||
|
"div": 10,
|
||||||
|
"min": 180,
|
||||||
|
"max": 207,
|
||||||
|
"def": 184,
|
||||||
|
"unit": "V"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LV1 Maximum Trip Time",
|
||||||
|
"div": 10,
|
||||||
|
"def": 1.5,
|
||||||
|
"unit": "s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "High Voltage 1",
|
||||||
|
"div": 10,
|
||||||
|
"min": 250,
|
||||||
|
"max": 270,
|
||||||
|
"def": 253,
|
||||||
|
"unit": "V"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "HV1 Maximum Trip Time",
|
||||||
|
"div": 10,
|
||||||
|
"min": 0.1,
|
||||||
|
"max": 100,
|
||||||
|
"def": 0.1,
|
||||||
|
"unit": "s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Low Voltage 2",
|
||||||
|
"div": 10,
|
||||||
|
"min": 80,
|
||||||
|
"max": 161,
|
||||||
|
"def": 104,
|
||||||
|
"unit": "V"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LV2 Maximum Trip Time",
|
||||||
|
"div": 100,
|
||||||
|
"min": 0.1,
|
||||||
|
"max": 5,
|
||||||
|
"def": 0.3,
|
||||||
|
"unit": "s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "High Voltage 2",
|
||||||
|
"div": 10,
|
||||||
|
"min": 230,
|
||||||
|
"max": 299,
|
||||||
|
"def": 276,
|
||||||
|
"unit": "V"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "HV2 Maximum Trip Time",
|
||||||
|
"div": 100,
|
||||||
|
"min": 0,
|
||||||
|
"max": 5,
|
||||||
|
"def": 0.05,
|
||||||
|
"unit": "s"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"0x000a": [
|
||||||
|
{
|
||||||
|
"name": "Nominal Voltage",
|
||||||
|
"div": 10,
|
||||||
|
"def": 230,
|
||||||
|
"unit": "V"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Low Voltage 1",
|
||||||
|
"div": 10,
|
||||||
|
"min": 160,
|
||||||
|
"max": 195.5,
|
||||||
|
"def": 184,
|
||||||
|
"unit": "V"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LV1 Maximum Trip Time",
|
||||||
|
"div": 10,
|
||||||
|
"def": 3,
|
||||||
|
"unit": "s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "High Voltage 1",
|
||||||
|
"div": 10,
|
||||||
|
"min": 270,
|
||||||
|
"max": 287.5,
|
||||||
|
"def": 287.5,
|
||||||
|
"unit": "V"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "HV1 Maximum Trip Time",
|
||||||
|
"div": 10,
|
||||||
|
"def": 0.1,
|
||||||
|
"unit": "s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Low Voltage 2",
|
||||||
|
"div": 10,
|
||||||
|
"max": 150,
|
||||||
|
"min": 100,
|
||||||
|
"def": 103.5,
|
||||||
|
"unit": "V"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LV2 Maximum Trip Time",
|
||||||
|
"div": 100,
|
||||||
|
"def": 0.3,
|
||||||
|
"unit": "s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "10 mins Average High Voltage",
|
||||||
|
"div": 10,
|
||||||
|
"min": 250,
|
||||||
|
"max": 270,
|
||||||
|
"def": 253,
|
||||||
|
"unit": "V"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"0x000c": [
|
||||||
|
{
|
||||||
|
"name": "Nominal Voltage",
|
||||||
|
"div": 10,
|
||||||
|
"unit": "V"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Low Voltage 1",
|
||||||
|
"div": 10,
|
||||||
|
"min": 180,
|
||||||
|
"max": 207,
|
||||||
|
"def": 184,
|
||||||
|
"unit": "V"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LV1 Maximum Trip Time",
|
||||||
|
"div": 10,
|
||||||
|
"min": 0.1,
|
||||||
|
"max": 5,
|
||||||
|
"def": 1.5,
|
||||||
|
"unit": "s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "High Voltage 1",
|
||||||
|
"div": 10,
|
||||||
|
"min": 250,
|
||||||
|
"max": 270,
|
||||||
|
"def": 253,
|
||||||
|
"unit": "V"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "HV1 Maximum Trip Time",
|
||||||
|
"div": 10,
|
||||||
|
"min": 0.1,
|
||||||
|
"max": 100,
|
||||||
|
"def": 3,
|
||||||
|
"unit": "s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Low Voltage 2",
|
||||||
|
"div": 10,
|
||||||
|
"min": 80,
|
||||||
|
"max": 161,
|
||||||
|
"def": 161,
|
||||||
|
"unit": "V"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LV2 Maximum Trip Time",
|
||||||
|
"div": 100,
|
||||||
|
"min": 0.1,
|
||||||
|
"max": 5,
|
||||||
|
"def": 0.2,
|
||||||
|
"unit": "s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "High Voltage 2",
|
||||||
|
"div": 10,
|
||||||
|
"min": 230,
|
||||||
|
"max": 299,
|
||||||
|
"def": 264.5,
|
||||||
|
"unit": "V"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "HV2 Maximum Trip Time",
|
||||||
|
"div": 100,
|
||||||
|
"min": 0.1,
|
||||||
|
"max": 5,
|
||||||
|
"def": 0.2,
|
||||||
|
"unit": "s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "High Voltage 3",
|
||||||
|
"div": 10,
|
||||||
|
"def": 276,
|
||||||
|
"unit": "V"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "HV3 Maximum Trip Time",
|
||||||
|
"div": 100,
|
||||||
|
"min": 0.1,
|
||||||
|
"max": 10,
|
||||||
|
"def": 0.1,
|
||||||
|
"unit": "s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "10 mins Average High Voltage",
|
||||||
|
"div": 10,
|
||||||
|
"def": 253,
|
||||||
|
"unit": "V"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"0x1000": [
|
||||||
|
{
|
||||||
|
"name": "Nominal Frequency",
|
||||||
|
"div": 100,
|
||||||
|
"def": 50,
|
||||||
|
"unit": "Hz"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Low Frequency 1",
|
||||||
|
"div": 100,
|
||||||
|
"min": 47.5,
|
||||||
|
"max": 49.9,
|
||||||
|
"def": 47.5,
|
||||||
|
"unit": "Hz"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LF1 Maximum Trip Time",
|
||||||
|
"div": 10,
|
||||||
|
"def": 0.1,
|
||||||
|
"unit": "s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "High Frequency 1",
|
||||||
|
"div": 100,
|
||||||
|
"min": 50.1,
|
||||||
|
"max": 51.5,
|
||||||
|
"def": 51.5,
|
||||||
|
"unit": "Hz"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "HF1 Maximum Trip Time",
|
||||||
|
"div": 10,
|
||||||
|
"def": 0.1,
|
||||||
|
"unit": "s"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"0x1003": [
|
||||||
|
{
|
||||||
|
"name": "Nominal Frequency",
|
||||||
|
"div": 100,
|
||||||
|
"def": 50,
|
||||||
|
"unit": "Hz"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Low Frequency 1",
|
||||||
|
"div": 100,
|
||||||
|
"min": 45,
|
||||||
|
"max": 49.9,
|
||||||
|
"def": 48,
|
||||||
|
"unit": "Hz"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LF1 Maximum Trip Time",
|
||||||
|
"div": 100,
|
||||||
|
"min": 0.1,
|
||||||
|
"max": 20,
|
||||||
|
"def": 2,
|
||||||
|
"unit": "s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "High Frequency 1",
|
||||||
|
"div": 100,
|
||||||
|
"min": 50,
|
||||||
|
"max": 53,
|
||||||
|
"def": 51,
|
||||||
|
"unit": "Hz"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "HF1 Maximum Trip time",
|
||||||
|
"div": 10,
|
||||||
|
"min": 0.1,
|
||||||
|
"max": 20,
|
||||||
|
"def": 2,
|
||||||
|
"unit": "s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Low Frequency 2",
|
||||||
|
"div": 100,
|
||||||
|
"min": 45,
|
||||||
|
"max": 50,
|
||||||
|
"def": 47.5,
|
||||||
|
"unit": "Hz"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LF2 Maximum Trip Time",
|
||||||
|
"div": 10,
|
||||||
|
"min": 0.1,
|
||||||
|
"max": 5,
|
||||||
|
"def": 0.5,
|
||||||
|
"unit": "s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "High Frequency 2",
|
||||||
|
"div": 100,
|
||||||
|
"min": 50,
|
||||||
|
"max": 52,
|
||||||
|
"def": 52,
|
||||||
|
"unit": "Hz"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "HF2 Maximum Trip time",
|
||||||
|
"div": 10,
|
||||||
|
"min": 0.1,
|
||||||
|
"max": 5,
|
||||||
|
"def": 0.5,
|
||||||
|
"unit": "s"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"0x2000": [
|
||||||
|
{
|
||||||
|
"name": "Island Detection Activated",
|
||||||
|
"div": 1,
|
||||||
|
"min": 0,
|
||||||
|
"max": 1,
|
||||||
|
"def": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"0x3003": [
|
||||||
|
{
|
||||||
|
"name": "Reconnect Time",
|
||||||
|
"div": 10,
|
||||||
|
"min": 10,
|
||||||
|
"max": 300,
|
||||||
|
"def": 60,
|
||||||
|
"unit": "s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Reconnect High Voltage",
|
||||||
|
"div": 10,
|
||||||
|
"min": 240,
|
||||||
|
"max": 276,
|
||||||
|
"def": 253,
|
||||||
|
"unit": "V"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Reconnect Low Voltage",
|
||||||
|
"div": 10,
|
||||||
|
"min": 195.5,
|
||||||
|
"max": 210,
|
||||||
|
"def": 195.5,
|
||||||
|
"unit": "V"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Reconnect High Frequency",
|
||||||
|
"div": 100,
|
||||||
|
"max": 50.9,
|
||||||
|
"min": 50.1,
|
||||||
|
"def": 50.2,
|
||||||
|
"unit": "Hz"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Reconnect Low Frequency",
|
||||||
|
"div": 100,
|
||||||
|
"min": 47.5,
|
||||||
|
"max": 49.9,
|
||||||
|
"def": 49.5,
|
||||||
|
"unit": "Hz"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"0x4000": [
|
||||||
|
{
|
||||||
|
"name": "Normal Ramp up Rate",
|
||||||
|
"div": 100,
|
||||||
|
"min": 0.1,
|
||||||
|
"max": 100,
|
||||||
|
"def": 20,
|
||||||
|
"unit": "Rated%/s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Soft Start Ramp up Rate ",
|
||||||
|
"div": 100,
|
||||||
|
"min": 0.1,
|
||||||
|
"max": 10,
|
||||||
|
"def": 0.16,
|
||||||
|
"unit": "Rated%/s"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"0x5001": [
|
||||||
|
{
|
||||||
|
"name": "FW Function Activated",
|
||||||
|
"div": 1,
|
||||||
|
"min": 0,
|
||||||
|
"max": 1,
|
||||||
|
"def": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Start of Frequency Watt Droop",
|
||||||
|
"div": 100,
|
||||||
|
"min": 50.2,
|
||||||
|
"max": 53,
|
||||||
|
"def": 50.2,
|
||||||
|
"unit": "Hz"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "FW Droop Slope",
|
||||||
|
"div": 10,
|
||||||
|
"min": 16.7,
|
||||||
|
"max": 100,
|
||||||
|
"def": 40,
|
||||||
|
"unit": "Pn%/Hz"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Recovery Ramp Rate",
|
||||||
|
"div": 100,
|
||||||
|
"min": 0.1,
|
||||||
|
"max": 100,
|
||||||
|
"def": 0.16,
|
||||||
|
"unit": "Pn%/s"
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "FW Setting Time",
|
||||||
|
"div": 10,
|
||||||
|
"min": 0,
|
||||||
|
"max": 2,
|
||||||
|
"def": 0,
|
||||||
|
"unit": "s"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"0x5008": [
|
||||||
|
{
|
||||||
|
"name": "FW Function Activated",
|
||||||
|
"div": 1,
|
||||||
|
"min": 0,
|
||||||
|
"max": 1,
|
||||||
|
"def": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Start of Frequency Watt Droop",
|
||||||
|
"div": 100,
|
||||||
|
"min": 50.2,
|
||||||
|
"max": 52,
|
||||||
|
"def": 50.2,
|
||||||
|
"unit": "Hz"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "FW Droop Slope",
|
||||||
|
"div": 10,
|
||||||
|
"min": 16.7,
|
||||||
|
"max": 100,
|
||||||
|
"def": 40,
|
||||||
|
"unit": "Pn%/Hz"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Recovery Ramp Rate",
|
||||||
|
"div": 100,
|
||||||
|
"min": 0.1,
|
||||||
|
"max": 50,
|
||||||
|
"def": 0.16,
|
||||||
|
"unit": "Pn%/s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Recovery High Frequency",
|
||||||
|
"div": 10,
|
||||||
|
"min": 50.1,
|
||||||
|
"max": 52,
|
||||||
|
"def": 50.2,
|
||||||
|
"unit": "Hz"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Recovery Low Frequency",
|
||||||
|
"div": 100,
|
||||||
|
"min": 49,
|
||||||
|
"max": 49.9,
|
||||||
|
"def": 49.8,
|
||||||
|
"unit": "Hz"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"0x6000": [
|
||||||
|
{
|
||||||
|
"name": "VW Function Activated",
|
||||||
|
"div": 1,
|
||||||
|
"min": 0,
|
||||||
|
"max": 1,
|
||||||
|
"def": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Start of Voltage Watt Droop",
|
||||||
|
"div": 10,
|
||||||
|
"def": 253,
|
||||||
|
"unit": "V"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "End of Voltage Watt Droop",
|
||||||
|
"div": 10,
|
||||||
|
"min": 258,
|
||||||
|
"max": 270,
|
||||||
|
"def": 265,
|
||||||
|
"unit": "V"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "VW Droop Slope",
|
||||||
|
"div": 100,
|
||||||
|
"min": 5,
|
||||||
|
"max": 18,
|
||||||
|
"def": 5.33,
|
||||||
|
"unit": "Pn%/V"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"0x7002": [
|
||||||
|
{
|
||||||
|
"name": "APC Function Activated",
|
||||||
|
"div": 1,
|
||||||
|
"min": 0,
|
||||||
|
"max": 1,
|
||||||
|
"def": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Power Ramp Rate",
|
||||||
|
"div": 100,
|
||||||
|
"min": 0.33,
|
||||||
|
"max": 100,
|
||||||
|
"def": 100,
|
||||||
|
"unit": "Pn%/s"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"0x8000": [
|
||||||
|
{
|
||||||
|
"name": "VV Function Activated",
|
||||||
|
"div": 1,
|
||||||
|
"min": 0,
|
||||||
|
"max": 1,
|
||||||
|
"def": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Voltage Set Point V1",
|
||||||
|
"div": 10,
|
||||||
|
"min": 184,
|
||||||
|
"max": 230,
|
||||||
|
"def": 213.9,
|
||||||
|
"unit": "V"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Reactive Set Point Q1",
|
||||||
|
"div": 10,
|
||||||
|
"min": 0,
|
||||||
|
"max": 100,
|
||||||
|
"def": 30,
|
||||||
|
"unit": "%Pn"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Voltage Set Point V2",
|
||||||
|
"div": 10,
|
||||||
|
"min": 210,
|
||||||
|
"max": 240,
|
||||||
|
"def": 223.1,
|
||||||
|
"unit": "V"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Voltage Set Point V3",
|
||||||
|
"div": 10,
|
||||||
|
"min": 220,
|
||||||
|
"max": 240,
|
||||||
|
"def": 236.9,
|
||||||
|
"unit": "V"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Voltage Set Point V4",
|
||||||
|
"div": 10,
|
||||||
|
"min": 230,
|
||||||
|
"max": 253,
|
||||||
|
"def": 246.1,
|
||||||
|
"unit": "V"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Reactive Set Point Q4",
|
||||||
|
"div": 10,
|
||||||
|
"min": 0,
|
||||||
|
"max": 100,
|
||||||
|
"def": 30,
|
||||||
|
"unit": "%Pn"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"0x8001": [
|
||||||
|
{
|
||||||
|
"name": "VV Function Activated",
|
||||||
|
"div": 1,
|
||||||
|
"min": 0,
|
||||||
|
"max": 1,
|
||||||
|
"def": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Voltage Set Point V1",
|
||||||
|
"div": 10,
|
||||||
|
"def": 213.9,
|
||||||
|
"unit": "V"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Reactive Set Point Q1",
|
||||||
|
"div": 10,
|
||||||
|
"min": 0,
|
||||||
|
"max": 100,
|
||||||
|
"def": 30,
|
||||||
|
"unit": "%Pn"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Voltage Set Point V2",
|
||||||
|
"div": 10,
|
||||||
|
"def": 223.1,
|
||||||
|
"unit": "V"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Voltage Set Point V3",
|
||||||
|
"div": 10,
|
||||||
|
"def": 236.9,
|
||||||
|
"unit": "V"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Voltage Set Point V4",
|
||||||
|
"div": 10,
|
||||||
|
"def": 246.1,
|
||||||
|
"unit": "V"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Reactive Set Point Q4",
|
||||||
|
"div": 10,
|
||||||
|
"min": 0,
|
||||||
|
"max": 100,
|
||||||
|
"def": 30,
|
||||||
|
"unit": "%Pn"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "VV Setting Time",
|
||||||
|
"div": 10,
|
||||||
|
"min": 0,
|
||||||
|
"max": 60,
|
||||||
|
"def": 10,
|
||||||
|
"unit": "s"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"0x9000": [
|
||||||
|
{
|
||||||
|
"name": "Specified Power Factor Activated",
|
||||||
|
"div": 1,
|
||||||
|
"min": 0,
|
||||||
|
"max": 1,
|
||||||
|
"def": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Power Factor",
|
||||||
|
"div": 100,
|
||||||
|
"min": 0.9,
|
||||||
|
"max": 1,
|
||||||
|
"def": 0.95
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"0xa002": [
|
||||||
|
{
|
||||||
|
"name": "RPC Function Activated",
|
||||||
|
"div": 1,
|
||||||
|
"min": 0,
|
||||||
|
"max": 1,
|
||||||
|
"def": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Reactive Power",
|
||||||
|
"div": 100,
|
||||||
|
"min": 0,
|
||||||
|
"max": 50,
|
||||||
|
"def": 0,
|
||||||
|
"unit": "%Sn"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"0xb000": [
|
||||||
|
{
|
||||||
|
"name": "WPF Function Activated",
|
||||||
|
"div": 1,
|
||||||
|
"min": 0,
|
||||||
|
"max": 1,
|
||||||
|
"def": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Start of Power of WPF",
|
||||||
|
"div": 10,
|
||||||
|
"def": 50,
|
||||||
|
"unit": "%Pn"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Power Factor ar Rated Power",
|
||||||
|
"div": 100,
|
||||||
|
"min": 0.8,
|
||||||
|
"max": 1,
|
||||||
|
"def": 0.95
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -34,8 +34,8 @@
|
||||||
html = "Settings successfully saved. Automatic page reload in 3 seconds.";
|
html = "Settings successfully saved. Automatic page reload in 3 seconds.";
|
||||||
meta.content = 3;
|
meta.content = 3;
|
||||||
} else {
|
} else {
|
||||||
html = "Settings successfully saved. Rebooting. Automatic redirect in 20 seconds.";
|
html = "Settings successfully saved. Rebooting. Automatic redirect in " + obj.reload + " seconds.";
|
||||||
meta.content = 20 + "; URL=/";
|
meta.content = obj.reload + "; URL=/";
|
||||||
}
|
}
|
||||||
document.getElementsByTagName('head')[0].appendChild(meta);
|
document.getElementsByTagName('head')[0].appendChild(meta);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -435,6 +435,31 @@
|
||||||
[47, "GPIO47"],
|
[47, "GPIO47"],
|
||||||
[48, "GPIO48"],
|
[48, "GPIO48"],
|
||||||
];
|
];
|
||||||
|
var esp32c3pins = [
|
||||||
|
[255, "off / default"],
|
||||||
|
[0, "GPIO0"],
|
||||||
|
[1, "GPIO1"],
|
||||||
|
[2, "GPIO2"],
|
||||||
|
[3, "GPIO3"],
|
||||||
|
[4, "GPIO4"],
|
||||||
|
[5, "GPIO5"],
|
||||||
|
[6, "GPIO6"],
|
||||||
|
[7, "GPIO7"],
|
||||||
|
[8, "GPIO8"],
|
||||||
|
[9, "GPIO9"],
|
||||||
|
[10, "GPIO10"],
|
||||||
|
[11, "GPIO11"],
|
||||||
|
[12, "GPIO12 (PSRAM/FLASH)"],
|
||||||
|
[13, "GPIO13 (PSRAM/FLASH)"],
|
||||||
|
[14, "GPIO14 (PSRAM/FLASH)"],
|
||||||
|
[15, "GPIO15 (PSRAM/FLASH)"],
|
||||||
|
[16, "GPIO16 (PSRAM/FLASH)"],
|
||||||
|
[17, "GPIO17 (PSRAM/FLASH)"],
|
||||||
|
[18, "GPIO18 (DONT USE - USB-)"],
|
||||||
|
[19, "GPIO19 (DONT USE - USB+)"],
|
||||||
|
[20, "GPIO20 (RX)"],
|
||||||
|
[21, "GPIO21 (TX)"],
|
||||||
|
];
|
||||||
/*ENDIF_ESP32*/
|
/*ENDIF_ESP32*/
|
||||||
var nrfPa = [
|
var nrfPa = [
|
||||||
[0, "MIN (recommended)"],
|
[0, "MIN (recommended)"],
|
||||||
|
@ -676,7 +701,7 @@
|
||||||
ml("td", {}, String(i+1)),
|
ml("td", {}, String(i+1)),
|
||||||
ml("td", {}, ml("input", {name: "ch_p"+i, class: "text", type: "number", max: 999, value: obj.ch_max_pwr[i]}, null)),
|
ml("td", {}, ml("input", {name: "ch_p"+i, class: "text", type: "number", max: 999, value: obj.ch_max_pwr[i]}, null)),
|
||||||
ml("td", {}, ml("input", {name: "ch_n"+i, class: "text", type: "text", maxlength: 15, value: (undefined === obj.ch_name[i]) ? "" : obj.ch_name[i]}, null)),
|
ml("td", {}, ml("input", {name: "ch_n"+i, class: "text", type: "text", maxlength: 15, value: (undefined === obj.ch_name[i]) ? "" : obj.ch_name[i]}, null)),
|
||||||
ml("td", {}, ml("input", {name: "yld_c"+i, class: "text", type: "number", max: 999999, value: obj.ch_yield_cor[i]}, null))
|
ml("td", {}, ml("input", {name: "yld_c"+i, class: "text", type: "number", max: 999999, value: obj.ch_yield_cor[i], step: "0.001"}, null))
|
||||||
]));
|
]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -872,13 +897,17 @@
|
||||||
|
|
||||||
function parsePinout(obj, type, system) {
|
function parsePinout(obj, type, system) {
|
||||||
var e = document.getElementById("pinout");
|
var e = document.getElementById("pinout");
|
||||||
|
var pinList = esp32pins;
|
||||||
|
if("ESP8266" == type) pinList = esp8266pins;
|
||||||
|
else if ("ESP32-S3" == system["chip_model"]) pinList = esp32s3pins;
|
||||||
|
else if("ESP32-C3" == system["chip_model"]) pinList = esp32c3pins;
|
||||||
pins = [['led0', 'pinLed0', 'At least one inverter is producing'], ['led1', 'pinLed1', 'MqTT connected']];
|
pins = [['led0', 'pinLed0', 'At least one inverter is producing'], ['led1', 'pinLed1', 'MqTT connected']];
|
||||||
for(p of pins) {
|
for(p of pins) {
|
||||||
e.append(
|
e.append(
|
||||||
ml("div", {class: "row mb-3"}, [
|
ml("div", {class: "row mb-3"}, [
|
||||||
ml("div", {class: "col-12 col-sm-3 my-2"}, p[2]),
|
ml("div", {class: "col-12 col-sm-3 my-2"}, p[2]),
|
||||||
ml("div", {class: "col-12 col-sm-9"},
|
ml("div", {class: "col-12 col-sm-9"},
|
||||||
sel(p[1], ("ESP8266" == type) ? esp8266pins : ("ESP32-S3" == system["chip_model"]) ? esp32s3pins : esp32pins, obj[p[0]])
|
sel(p[1], pinList, obj[p[0]])
|
||||||
)
|
)
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
|
@ -898,6 +927,11 @@
|
||||||
var en = inp("nrfEnable", null, null, ["cb"], "nrfEnable", "checkbox");
|
var en = inp("nrfEnable", null, null, ["cb"], "nrfEnable", "checkbox");
|
||||||
en.checked = obj["en"];
|
en.checked = obj["en"];
|
||||||
|
|
||||||
|
var pinList = esp32pins;
|
||||||
|
if("ESP8266" == type) pinList = esp8266pins;
|
||||||
|
else if ("ESP32-S3" == system["chip_model"]) pinList = esp32s3pins;
|
||||||
|
else if("ESP32-C3" == system["chip_model"]) pinList = esp32c3pins;
|
||||||
|
|
||||||
e.replaceChildren (
|
e.replaceChildren (
|
||||||
ml("div", {class: "row mb-3"}, [
|
ml("div", {class: "row mb-3"}, [
|
||||||
ml("div", {class: "col-8 col-sm-3 my-2"}, "NRF24 Enable"),
|
ml("div", {class: "col-8 col-sm-3 my-2"}, "NRF24 Enable"),
|
||||||
|
@ -915,7 +949,7 @@
|
||||||
ml("div", {class: "row mb-3"}, [
|
ml("div", {class: "row mb-3"}, [
|
||||||
ml("div", {class: "col-12 col-sm-3 my-2"}, p[0].toUpperCase()),
|
ml("div", {class: "col-12 col-sm-3 my-2"}, p[0].toUpperCase()),
|
||||||
ml("div", {class: "col-12 col-sm-9"},
|
ml("div", {class: "col-12 col-sm-9"},
|
||||||
sel(p[1], ("ESP8266" == type) ? esp8266pins : ("ESP32-S3" == system["chip_model"]) ? esp32s3pins : esp32pins, objPin[p[0]])
|
sel(p[1], pinList, objPin[p[0]])
|
||||||
)
|
)
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
|
@ -926,6 +960,10 @@
|
||||||
function parseCmtRadio(obj, type, system) {
|
function parseCmtRadio(obj, type, system) {
|
||||||
var e = document.getElementById("cmt");
|
var e = document.getElementById("cmt");
|
||||||
var en = inp("cmtEnable", null, null, ["cb"], "cmtEnable", "checkbox");
|
var en = inp("cmtEnable", null, null, ["cb"], "cmtEnable", "checkbox");
|
||||||
|
var pinList = esp32pins;
|
||||||
|
if ("ESP32-S3" == system["chip_model"]) pinList = esp32s3pins;
|
||||||
|
else if("ESP32-C3" == system["chip_model"]) pinList = esp32c3pins;
|
||||||
|
|
||||||
en.checked = obj["en"];
|
en.checked = obj["en"];
|
||||||
|
|
||||||
e.replaceChildren (
|
e.replaceChildren (
|
||||||
|
@ -940,7 +978,7 @@
|
||||||
ml("div", {class: "row mb-3"}, [
|
ml("div", {class: "row mb-3"}, [
|
||||||
ml("div", {class: "col-12 col-sm-3 my-2"}, p[0].toUpperCase()),
|
ml("div", {class: "col-12 col-sm-3 my-2"}, p[0].toUpperCase()),
|
||||||
ml("div", {class: "col-12 col-sm-9"},
|
ml("div", {class: "col-12 col-sm-9"},
|
||||||
sel(p[1], (("ESP32-S3" == system["chip_model"]) ? esp32s3pins : esp32pins), obj[p[0]])
|
sel(p[1], pinList, obj[p[0]])
|
||||||
)
|
)
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
|
@ -954,6 +992,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseDisplay(obj, type, system) {
|
function parseDisplay(obj, type, system) {
|
||||||
|
var pinList = esp32pins;
|
||||||
|
if("ESP8266" == type) pinList = esp8266pirpins;
|
||||||
|
else if ("ESP32-S3" == system["chip_model"]) pinList = esp32s3pins;
|
||||||
|
else if("ESP32-C3" == system["chip_model"]) pinList = esp32c3pins;
|
||||||
|
|
||||||
for(var i of ["disp_pwr"])
|
for(var i of ["disp_pwr"])
|
||||||
document.getElementsByName(i)[0].checked = obj[i];
|
document.getElementsByName(i)[0].checked = obj[i];
|
||||||
|
|
||||||
|
@ -968,7 +1011,7 @@
|
||||||
ml("div", {class: "row mb-3", id: "row_" + p[1]}, [
|
ml("div", {class: "row mb-3", id: "row_" + p[1]}, [
|
||||||
ml("div", {class: "col-12 col-sm-3 my-2"}, p[0].toUpperCase()),
|
ml("div", {class: "col-12 col-sm-3 my-2"}, p[0].toUpperCase()),
|
||||||
ml("div", {class: "col-12 col-sm-9"},
|
ml("div", {class: "col-12 col-sm-9"},
|
||||||
sel(p[1], ("ESP8266" == type) ? esp8266pins : ("ESP32-S3" == system["chip_model"]) ? esp32s3pins : esp32pins, obj[p[1]])
|
sel(p[1], pinList, obj[p[1]])
|
||||||
)
|
)
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
|
@ -1018,7 +1061,7 @@
|
||||||
document.getElementById("pirPin").append(
|
document.getElementById("pirPin").append(
|
||||||
ml("div", {class: "row mb-3"}, [
|
ml("div", {class: "row mb-3"}, [
|
||||||
ml("div", {class: "col-12 col-sm-3 my-2"}, "PIR sensor"),
|
ml("div", {class: "col-12 col-sm-3 my-2"}, "PIR sensor"),
|
||||||
ml("div", {class: "col-12 col-sm-9"}, sel("pir_pin", ("ESP8266" == type) ? esp8266pirpins : ("ESP32-S3" == system["chip_model"]) ? esp32s3pins : esp32pins, obj["pir_pin"]))
|
ml("div", {class: "col-12 col-sm-9"}, sel("pir_pin", pinList, obj["pir_pin"]))
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -295,13 +295,76 @@
|
||||||
getAjax("/api/inverter/grid/" + obj.id, showGridProfile);
|
getAjax("/api/inverter/grid/" + obj.id, showGridProfile);
|
||||||
}}, null))
|
}}, null))
|
||||||
])
|
])
|
||||||
]);
|
])
|
||||||
modal("Info for inverter " + obj.name, ml("div", {}, html));
|
modal("Info for inverter " + obj.name, ml("div", {}, html))
|
||||||
|
}
|
||||||
|
|
||||||
|
function getGridValue(g) {
|
||||||
|
var val = (parseInt(g.grid.substring(g.offs*3, g.offs*3+2), 16) * 256)
|
||||||
|
+ parseInt(g.grid.substring(g.offs*3+3, g.offs*3+5), 16)
|
||||||
|
g.offs += 2
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
|
function getGridIdentifier(g) {
|
||||||
|
return "0x" + getGridValue(g).toString(16).padStart(4, '0')
|
||||||
|
}
|
||||||
|
|
||||||
|
function getGridType(t, id) {
|
||||||
|
for(e of t) {
|
||||||
|
if(undefined !== e[id])
|
||||||
|
return e[id]
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseGridGroup(g) {
|
||||||
|
var id = getGridIdentifier(g)
|
||||||
|
var type = getGridType(g.info.grp_codes, id.substring(0, 4))
|
||||||
|
var content = []
|
||||||
|
content.push(ml("div", {class: "row"},
|
||||||
|
ml("div", {class: "col head p-2 mt-3"},
|
||||||
|
ml("div", {class: "col a-c"}, type + " (Code " + id + ")")
|
||||||
|
)
|
||||||
|
))
|
||||||
|
content.push(ml("div", {class: "row my-2"}, [
|
||||||
|
ml("div", {class: "col-4"}, ml("b", {}, "Name")),
|
||||||
|
ml("div", {class: "col-3"}, ml("b", {}, "Value")),
|
||||||
|
ml("div", {class: "col-3"}, ml("b", {}, "Range")),
|
||||||
|
ml("div", {class: "col-2"}, ml("b", {}, "Default"))
|
||||||
|
]))
|
||||||
|
for(e of g.info.group) {
|
||||||
|
if(Array.isArray(e[id])) {
|
||||||
|
for(e of e[id]) {
|
||||||
|
var v = String(getGridValue(g) / e.div);
|
||||||
|
var vt = (v !== String(e.def)) ? "b" : "span";
|
||||||
|
content.push(ml("div", {class: "row mt-2"}, [
|
||||||
|
ml("div", {class: "col-4"}, e.name),
|
||||||
|
ml("div", {class: "col-3"}, ml(vt, {}, v + ((undefined !== e.unit) ? " [" + e.unit + "]" : ""))),
|
||||||
|
ml("div", {class: "col-3"}, (undefined !== e.min) ? (e.min + " - " + e.max) : "n/a"),
|
||||||
|
ml("div", {class: "col-2"}, String(e.def))
|
||||||
|
]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ml("div", {class: "col"}, [...content])
|
||||||
}
|
}
|
||||||
|
|
||||||
function showGridProfile(obj) {
|
function showGridProfile(obj) {
|
||||||
var html = ml("pre", {}, obj.grid);
|
getJSON("/grid_info.json").then(data => {
|
||||||
modal("Grid Profile for inverter " + obj.name, ml("div", {}, html));
|
var glob = {offs:0, grid:obj.grid, info: data}
|
||||||
|
var content = [];
|
||||||
|
content.push(ml("div", {class: "row"},
|
||||||
|
ml("div", {class: "col my-3"}, ml("h5", {}, getGridType(glob.info.type, getGridIdentifier(glob)) + " (Version " + getGridValue(glob).toString(16) + ")"))
|
||||||
|
))
|
||||||
|
|
||||||
|
while((glob.offs*3) < glob.grid.length) {
|
||||||
|
content.push(parseGridGroup(glob))
|
||||||
|
}
|
||||||
|
|
||||||
|
modal("Grid Profile for inverter " + obj.name, ml("div", {}, ml("div", {class: "col mb-2"}, [...content])))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -315,8 +378,8 @@
|
||||||
tr2(["RX fragments", obj.frame_cnt, ""]),
|
tr2(["RX fragments", obj.frame_cnt, ""]),
|
||||||
tr2(["TX retransmits", obj.retransmits, ""])
|
tr2(["TX retransmits", obj.retransmits, ""])
|
||||||
])
|
])
|
||||||
]);
|
])
|
||||||
modal("Radio statistics for inverter " + obj.name, ml("div", {}, html));
|
modal("Radio statistics for inverter " + obj.name, ml("div", {}, html))
|
||||||
}
|
}
|
||||||
|
|
||||||
function limitModal(obj) {
|
function limitModal(obj) {
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "html/h/colorBright_css.h"
|
#include "html/h/colorBright_css.h"
|
||||||
#include "html/h/colorDark_css.h"
|
#include "html/h/colorDark_css.h"
|
||||||
#include "html/h/favicon_ico.h"
|
#include "html/h/favicon_ico.h"
|
||||||
|
#include "html/h/grid_info_json.h"
|
||||||
#include "html/h/index_html.h"
|
#include "html/h/index_html.h"
|
||||||
#include "html/h/login_html.h"
|
#include "html/h/login_html.h"
|
||||||
#include "html/h/serial_html.h"
|
#include "html/h/serial_html.h"
|
||||||
|
@ -65,6 +66,7 @@ class Web {
|
||||||
mWeb.on("/colors.css", HTTP_GET, std::bind(&Web::onColor, this, std::placeholders::_1));
|
mWeb.on("/colors.css", HTTP_GET, std::bind(&Web::onColor, this, std::placeholders::_1));
|
||||||
mWeb.on("/style.css", HTTP_GET, std::bind(&Web::onCss, this, std::placeholders::_1));
|
mWeb.on("/style.css", HTTP_GET, std::bind(&Web::onCss, this, std::placeholders::_1));
|
||||||
mWeb.on("/api.js", HTTP_GET, std::bind(&Web::onApiJs, this, std::placeholders::_1));
|
mWeb.on("/api.js", HTTP_GET, std::bind(&Web::onApiJs, this, std::placeholders::_1));
|
||||||
|
mWeb.on("/grid_info.json", HTTP_GET, std::bind(&Web::onGridInfoJson, this, std::placeholders::_1));
|
||||||
mWeb.on("/favicon.ico", HTTP_GET, std::bind(&Web::onFavicon, this, std::placeholders::_1));
|
mWeb.on("/favicon.ico", HTTP_GET, std::bind(&Web::onFavicon, this, std::placeholders::_1));
|
||||||
mWeb.onNotFound ( std::bind(&Web::showNotFound, this, std::placeholders::_1));
|
mWeb.onNotFound ( std::bind(&Web::showNotFound, this, std::placeholders::_1));
|
||||||
mWeb.on("/reboot", HTTP_ANY, std::bind(&Web::onReboot, this, std::placeholders::_1));
|
mWeb.on("/reboot", HTTP_ANY, std::bind(&Web::onReboot, this, std::placeholders::_1));
|
||||||
|
@ -389,6 +391,16 @@ class Web {
|
||||||
request->send(response);
|
request->send(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void onGridInfoJson(AsyncWebServerRequest *request) {
|
||||||
|
DPRINTLN(DBG_VERBOSE, F("onGridInfoJson"));
|
||||||
|
|
||||||
|
AsyncWebServerResponse *response = request->beginResponse_P(200, F("application/json; charset=utf-8"), grid_info_json, grid_info_json_len);
|
||||||
|
response->addHeader(F("Content-Encoding"), "gzip");
|
||||||
|
if(request->hasParam("v"))
|
||||||
|
response->addHeader(F("Cache-Control"), F("max-age=604800"));
|
||||||
|
request->send(response);
|
||||||
|
}
|
||||||
|
|
||||||
void onFavicon(AsyncWebServerRequest *request) {
|
void onFavicon(AsyncWebServerRequest *request) {
|
||||||
static const char favicon_type[] PROGMEM = "image/x-icon";
|
static const char favicon_type[] PROGMEM = "image/x-icon";
|
||||||
AsyncWebServerResponse *response = request->beginResponse_P(200, favicon_type, favicon_ico, favicon_ico_len);
|
AsyncWebServerResponse *response = request->beginResponse_P(200, favicon_type, favicon_ico, favicon_ico_len);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue