Browse Source

Merge branch 'development03' into development03_merge

pull/1491/head
VArt67 1 year ago
committed by GitHub
parent
commit
2808781eb2
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 2
      .github/workflows/compile_development.yml
  2. 149
      scripts/convertHtml.py
  3. 40
      scripts/htmlPreprocessorDefines.py
  4. 16
      src/CHANGES.md
  5. 6
      src/config/settings.h
  6. 4
      src/defines.h
  7. 4
      src/hm/Communication.h
  8. 15
      src/hm/Heuristic.h
  9. 50
      src/hm/hmInverter.h
  10. 7
      src/hm/hmSystem.h
  11. 4
      src/platformio.ini
  12. 2
      src/publisher/pubMqtt.h
  13. 2
      src/publisher/pubMqttIvData.h
  14. 4
      src/utils/scheduler.h
  15. 2
      src/web/RestApi.h
  16. 4
      src/web/html/api.js
  17. 11
      src/web/html/includes/nav.html
  18. 116
      src/web/html/setup.html
  19. 2
      src/web/html/style.css
  20. 2
      src/web/web.h

2
.github/workflows/compile_development.yml

@ -24,9 +24,11 @@ jobs:
matrix: matrix:
variant: variant:
- esp8266 - esp8266
- esp8266-minimal
- esp8266-prometheus - esp8266-prometheus
- esp8285 - esp8285
- esp32-wroom32 - esp32-wroom32
- esp32-wroom32-minimal
- esp32-wroom32-prometheus - esp32-wroom32-prometheus
- esp32-wroom32-ethernet - esp32-wroom32-ethernet
- esp32-s2-mini - esp32-s2-mini

149
scripts/convertHtml.py

@ -7,8 +7,37 @@ import json
from datetime import date from datetime import date
from pathlib import Path from pathlib import Path
import subprocess import subprocess
import configparser
Import("env") Import("env")
import htmlPreprocessorDefines as prepro
def get_build_flags():
config = configparser.ConfigParser()
config.read('platformio.ini')
global build_flags
build_flags = config["env:" + env['PIOENV']]['build_flags'].split('\n')
for i in range(len(build_flags)):
build_flags[i] = build_flags[i][2:]
# translate board
board = config["env:" + env['PIOENV']]['board']
if board == "esp12e" or board == "esp8285":
build_flags.append("ESP8266")
elif board == "lolin_d32":
build_flags.append("ESP32")
elif board == "lolin_s2_mini":
build_flags.append("ESP32")
build_flags.append("ESP32-S2")
elif board == "lolin_c3_mini":
build_flags.append("ESP32")
build_flags.append("ESP32-C3")
elif board == "esp32-s3-devkitc-1":
build_flags.append("ESP32")
build_flags.append("ESP32-S3")
def get_git_sha(): def get_git_sha():
try: try:
@ -50,38 +79,46 @@ def readVersionFull(path):
return version return version
def htmlParts(file, header, nav, footer, versionPath, lang): def htmlParts(file, header, nav, footer, versionPath, lang):
p = "";
f = open(file, "r") f = open(file, "r")
lines = f.readlines() lines = f.readlines()
f.close(); f.close();
f = open(header, "r") f = open(header, "r")
h = f.read().strip() h = f.readlines()
f.close() f.close()
f = open(nav, "r") f = open(nav, "r")
n = f.read().strip() n = f.readlines()
f.close() f.close()
f = open(footer, "r") f = open(footer, "r")
fo = f.read().strip() fo = f.readlines()
f.close() f.close()
linesExt = []
for line in lines: for line in lines:
line = line.replace("{#HTML_HEADER}", h) if line.find("{#HTML_HEADER}") != -1:
line = line.replace("{#HTML_NAV}", n) linesExt.extend(h)
line = line.replace("{#HTML_FOOTER}", fo) elif line.find("{#HTML_NAV}") != -1:
p += line linesExt.extend(n)
elif line.find("{#HTML_FOOTER}") != -1:
linesExt.extend(fo)
else:
linesExt.append(line)
linesMod = prepro.conv(linesExt, build_flags)
#placeholders #placeholders
version = readVersion(versionPath); version = readVersion(versionPath);
link = '<a target="_blank" href="https://github.com/lumapu/ahoy/commits/' + get_git_sha() + '">GIT SHA: ' + get_git_sha() + ' :: ' + version + '</a>' link = '<a target="_blank" href="https://github.com/lumapu/ahoy/commits/' + get_git_sha() + '">GIT SHA: ' + get_git_sha() + ' :: ' + version + '</a>'
p = ""
for line in linesMod:
p += line
p = p.replace("{#VERSION}", version) p = p.replace("{#VERSION}", version)
p = p.replace("{#VERSION_FULL}", readVersionFull(versionPath)) p = p.replace("{#VERSION_FULL}", readVersionFull(versionPath))
p = p.replace("{#VERSION_GIT}", link) p = p.replace("{#VERSION_GIT}", link)
# remove if - endif ESP32
p = checkIf(p)
p = translate(file, p, lang) p = translate(file, p, lang)
p = translate("general", p, lang) # menu / header / footer p = translate("general", p, lang) # menu / header / footer
@ -90,30 +127,6 @@ def htmlParts(file, header, nav, footer, versionPath, lang):
f.close(); f.close();
return p return p
def checkIf(data):
if (env['PIOENV'][0:5] == "esp32") or env['PIOENV'][0:4] == "open":
data = data.replace("<!--IF_ESP32-->", "")
data = data.replace("<!--ENDIF_ESP32-->", "")
data = data.replace("/*IF_ESP32*/", "")
data = data.replace("/*ENDIF_ESP32*/", "")
else:
while 1:
start = data.find("<!--IF_ESP32-->")
end = data.find("<!--ENDIF_ESP32-->")+18
if -1 == start:
break
else:
data = data[0:start] + data[end:]
while 1:
start = data.find("/*IF_ESP32*/")
end = data.find("/*ENDIF_ESP32*/")+15
if -1 == start:
break
else:
data = data[0:start] + data[end:]
return data
def findLang(file): def findLang(file):
with open('../lang.json') as j: with open('../lang.json') as j:
lang = json.load(j) lang = json.load(j)
@ -189,33 +202,41 @@ def convert2Header(inFile, versionPath, lang):
f.write("#endif /*__{}_{}_H__*/\n".format(define, define2)) f.write("#endif /*__{}_{}_H__*/\n".format(define, define2))
f.close() f.close()
# delete all files in the 'h' dir
wd = 'web/html/h' def main():
get_build_flags()
if os.path.exists(wd):
for f in os.listdir(wd): # delete all files in the 'h' dir
os.remove(os.path.join(wd, f)) wd = 'web/html/h'
wd += "/tmp"
if os.path.exists(wd): if os.path.exists(wd):
for f in os.listdir(wd): for f in os.listdir(wd):
os.remove(os.path.join(wd, f)) os.remove(os.path.join(wd, f))
wd += "/tmp"
# grab all files with following extensions if os.path.exists(wd):
os.chdir('./web/html') for f in os.listdir(wd):
types = ('*.html', '*.css', '*.js', '*.ico', '*.json') # the tuple of file types os.remove(os.path.join(wd, f))
files_grabbed = []
for files in types: # grab all files with following extensions
files_grabbed.extend(glob.glob(files)) os.chdir('./web/html')
types = ('*.html', '*.css', '*.js', '*.ico', '*.json') # the tuple of file types
Path("h").mkdir(exist_ok=True) files_grabbed = []
Path("tmp").mkdir(exist_ok=True) # created to check if webpages are valid with all replacements for files in types:
shutil.copyfile("style.css", "tmp/style.css") files_grabbed.extend(glob.glob(files))
# get language from environment Path("h").mkdir(exist_ok=True)
lang = "en" Path("tmp").mkdir(exist_ok=True) # created to check if webpages are valid with all replacements
if env['PIOENV'][-3:] == "-de": shutil.copyfile("style.css", "tmp/style.css")
lang = "de"
# get language from environment
# go throw the array lang = "en"
for val in files_grabbed: if env['PIOENV'][-3:] == "-de":
convert2Header(val, "../../defines.h", lang) lang = "de"
# go throw the array
for val in files_grabbed:
convert2Header(val, "../../defines.h", lang)
main()

40
scripts/htmlPreprocessorDefines.py

@ -0,0 +1,40 @@
import re
import os
import queue
def error(msg):
print("ERROR: " + msg)
exit()
def check(inp, lst, pattern):
q = queue.LifoQueue()
out = []
keep = True
for line in inp:
x = re.findall(pattern, line)
if len(x) > 0:
if line.find("ENDIF_") != -1:
if not q.empty():
e = q.get()
if e[0] == x[0]:
keep = e[1]
elif line.find("IF_") != -1:
q.put((x[0], keep))
if keep is True:
keep = x[0] in lst
elif line.find("E") != -1:
if q.empty():
error("(ELSE) missing open statement!")
e = q.get()
q.put(e)
if e[1] is True:
keep = not keep
else:
if keep is True:
out.append(line)
return out
def conv(inp, lst):
print(lst)
out = check(inp, lst, r'\/\*(?:IF_|ELS|ENDIF_)([A-Z0-9\-_]+)?\*\/')
return check(out, lst, r'\<\!\-\-(?:IF_|ELS|ENDIF_)([A-Z0-9\-_]+)?\-\-\>')

16
src/CHANGES.md

@ -1,5 +1,17 @@
# Development Changes # Development Changes
## 0.8.91 - 2024-03-05
* fix javascript issues #1480
## 0.8.90 - 2024-03-05
* added preprocessor defines to HTML (from platform.ini) to reduce the HTML in size if modules aren't enabled
* auto build minimal English versions of ESP8266 and ESP32
## 0.8.89 - 2024-03-02
* merge PR: Collection of small fixes #1465
* fix: show esp type on `/history` #1463
* improved HMS-400-1T support (serial number 1125...) #1460
## 0.8.88 - 2024-02-28 ## 0.8.88 - 2024-02-28
* fix MqTT statistic data overflow #1458 * fix MqTT statistic data overflow #1458
* add HMS-400-1T support (serial number 1125...) #1460 * add HMS-400-1T support (serial number 1125...) #1460
@ -265,7 +277,7 @@
## 0.8.39 - 2024-01-01 ## 0.8.39 - 2024-01-01
* fix MqTT dis_night_comm in the morning #1309 #1286 * fix MqTT dis_night_comm in the morning #1309 #1286
* seperated offset for sunrise and sunset #1308 * separated offset for sunrise and sunset #1308
* powerlimit (active power control) now has one decimal place (MqTT / API) #1199 * powerlimit (active power control) now has one decimal place (MqTT / API) #1199
* merge Prometheus metrics fix #1310 * merge Prometheus metrics fix #1310
* merge MI grid profile request #1306 * merge MI grid profile request #1306
@ -478,7 +490,7 @@
## 0.7.61 - 2023-10-01 ## 0.7.61 - 2023-10-01
* merged `hmPayload` and `hmsPayload` into single class * merged `hmPayload` and `hmsPayload` into single class
* merged generic radio functions into new parent class `radio.h` * merged generic radio functions into new parent class `radio.h`
* moved radio statistics into the inverter - each inverter has now seperate statistics which can be accessed by click on the footer in `/live` * moved radio statistics into the inverter - each inverter has now separate statistics which can be accessed by click on the footer in `/live`
* fix compiler warnings #1191 * fix compiler warnings #1191
* fix ePaper logo during night time #1151 * fix ePaper logo during night time #1151

6
src/config/settings.h

@ -152,7 +152,7 @@ typedef struct {
} cfgIv_t; } cfgIv_t;
typedef struct { typedef struct {
bool enabled; // bool enabled;
cfgIv_t iv[MAX_NUM_INVERTERS]; cfgIv_t iv[MAX_NUM_INVERTERS];
uint16_t sendInterval; uint16_t sendInterval;
@ -755,7 +755,7 @@ class settings {
void jsonInst(JsonObject obj, bool set = false) { void jsonInst(JsonObject obj, bool set = false) {
if(set) { if(set) {
obj[F("intvl")] = mCfg.inst.sendInterval; obj[F("intvl")] = mCfg.inst.sendInterval;
obj[F("en")] = (bool)mCfg.inst.enabled; // obj[F("en")] = (bool)mCfg.inst.enabled;
obj[F("rstMidNight")] = (bool)mCfg.inst.rstYieldMidNight; obj[F("rstMidNight")] = (bool)mCfg.inst.rstYieldMidNight;
obj[F("rstNotAvail")] = (bool)mCfg.inst.rstValsNotAvail; obj[F("rstNotAvail")] = (bool)mCfg.inst.rstValsNotAvail;
obj[F("rstComStop")] = (bool)mCfg.inst.rstValsCommStop; obj[F("rstComStop")] = (bool)mCfg.inst.rstValsCommStop;
@ -765,7 +765,7 @@ class settings {
} }
else { else {
getVal<uint16_t>(obj, F("intvl"), &mCfg.inst.sendInterval); getVal<uint16_t>(obj, F("intvl"), &mCfg.inst.sendInterval);
getVal<bool>(obj, F("en"), &mCfg.inst.enabled); // getVal<bool>(obj, F("en"), &mCfg.inst.enabled);
getVal<bool>(obj, F("rstMidNight"), &mCfg.inst.rstYieldMidNight); getVal<bool>(obj, F("rstMidNight"), &mCfg.inst.rstYieldMidNight);
getVal<bool>(obj, F("rstNotAvail"), &mCfg.inst.rstValsNotAvail); getVal<bool>(obj, F("rstNotAvail"), &mCfg.inst.rstValsNotAvail);
getVal<bool>(obj, F("rstComStop"), &mCfg.inst.rstValsCommStop); getVal<bool>(obj, F("rstComStop"), &mCfg.inst.rstValsCommStop);

4
src/defines.h

@ -13,7 +13,7 @@
//------------------------------------- //-------------------------------------
#define VERSION_MAJOR 0 #define VERSION_MAJOR 0
#define VERSION_MINOR 8 #define VERSION_MINOR 8
#define VERSION_PATCH 88 #define VERSION_PATCH 91
//------------------------------------- //-------------------------------------
typedef struct { typedef struct {
@ -109,7 +109,7 @@ enum {
typedef struct { typedef struct {
uint32_t rxFail; uint32_t rxFail;
uint32_t rxFailNoAnser; uint32_t rxFailNoAnswer;
uint32_t rxSuccess; uint32_t rxSuccess;
uint32_t frmCnt; uint32_t frmCnt;
uint32_t txCnt; uint32_t txCnt;

4
src/hm/Communication.h

@ -117,7 +117,7 @@ class Communication : public CommQueue<> {
//q->iv->radioStatistics.txCnt++; //q->iv->radioStatistics.txCnt++;
q->iv->radio->mRadioWaitTime.startTimeMonitor(mTimeout); q->iv->radio->mRadioWaitTime.startTimeMonitor(mTimeout);
if(!mIsRetransmit && (q->cmd == AlarmData) || (q->cmd == GridOnProFilePara)) if((!mIsRetransmit && (q->cmd == AlarmData)) || (q->cmd == GridOnProFilePara))
incrAttempt((q->cmd == AlarmData)? MORE_ATTEMPS_ALARMDATA : MORE_ATTEMPS_GRIDONPROFILEPARA); incrAttempt((q->cmd == AlarmData)? MORE_ATTEMPS_ALARMDATA : MORE_ATTEMPS_GRIDONPROFILEPARA);
mIsRetransmit = false; mIsRetransmit = false;
@ -622,7 +622,7 @@ class Communication : public CommQueue<> {
else if(q->iv->mGotFragment || mCompleteRetry) else if(q->iv->mGotFragment || mCompleteRetry)
q->iv->radioStatistics.rxFail++; // got no complete payload q->iv->radioStatistics.rxFail++; // got no complete payload
else else
q->iv->radioStatistics.rxFailNoAnser++; // got nothing q->iv->radioStatistics.rxFailNoAnswer++; // got nothing
mWaitTime.startTimeMonitor(1); // maybe remove, side effects unknown mWaitTime.startTimeMonitor(1); // maybe remove, side effects unknown
bool keep = false; bool keep = false;

15
src/hm/Heuristic.h

@ -153,7 +153,7 @@ class Heuristic {
DBGPRINT(F(", f: ")); DBGPRINT(F(", f: "));
DBGPRINT(String(iv->radioStatistics.rxFail)); DBGPRINT(String(iv->radioStatistics.rxFail));
DBGPRINT(F(", n: ")); DBGPRINT(F(", n: "));
DBGPRINT(String(iv->radioStatistics.rxFailNoAnser)); DBGPRINT(String(iv->radioStatistics.rxFailNoAnswer));
DBGPRINT(F(" | p: ")); // better debugging for helpers... DBGPRINT(F(" | p: ")); // better debugging for helpers...
if((IV_HMS == iv->ivGen) || (IV_HMT == iv->ivGen)) if((IV_HMS == iv->ivGen) || (IV_HMT == iv->ivGen))
DBGPRINTLN(String(iv->config->powerLevel-10)); DBGPRINTLN(String(iv->config->powerLevel-10));
@ -217,15 +217,12 @@ class Heuristic {
} }
inline uint8_t id2Ch(uint8_t id) { inline uint8_t id2Ch(uint8_t id) {
switch(id) { if (id < RF_MAX_CHANNEL_ID)
case 0: return 3; return mChList[id];
case 1: return 23; else
case 2: return 40; return 3; // standard
case 3: return 61;
case 4: return 75;
}
return 3; // standard
} }
uint8_t mChList[RF_MAX_CHANNEL_ID] = {03, 23, 40, 61, 75};
}; };

50
src/hm/hmInverter.h

@ -288,32 +288,30 @@ class Inverter {
uint8_t end = ptr + rec->assign[pos].num; uint8_t end = ptr + rec->assign[pos].num;
uint16_t div = rec->assign[pos].div; uint16_t div = rec->assign[pos].div;
if(NULL != rec) { if(CMD_CALC != div) {
if(CMD_CALC != div) { uint32_t val = 0;
uint32_t val = 0; do {
do { val <<= 8;
val <<= 8; val |= buf[ptr];
val |= buf[ptr]; } while(++ptr != end);
} while(++ptr != end);
if ((FLD_T == rec->assign[pos].fieldId) || (FLD_Q == rec->assign[pos].fieldId) || (FLD_PF == rec->assign[pos].fieldId)) {
if ((FLD_T == rec->assign[pos].fieldId) || (FLD_Q == rec->assign[pos].fieldId) || (FLD_PF == rec->assign[pos].fieldId)) { // temperature, Qvar, and power factor are a signed values
// temperature, Qvar, and power factor are a signed values rec->record[pos] = ((REC_TYP)((int16_t)val)) / (REC_TYP)(div);
rec->record[pos] = ((REC_TYP)((int16_t)val)) / (REC_TYP)(div); } else if (FLD_YT == rec->assign[pos].fieldId) {
} else if (FLD_YT == rec->assign[pos].fieldId) { rec->record[pos] = ((REC_TYP)(val) / (REC_TYP)(div)) + ((REC_TYP)config->yieldCor[rec->assign[pos].ch-1]);
rec->record[pos] = ((REC_TYP)(val) / (REC_TYP)(div)) + ((REC_TYP)config->yieldCor[rec->assign[pos].ch-1]); } else if (FLD_YD == rec->assign[pos].fieldId) {
} else if (FLD_YD == rec->assign[pos].fieldId) { float actYD = (REC_TYP)(val) / (REC_TYP)(div);
float actYD = (REC_TYP)(val) / (REC_TYP)(div); uint8_t idx = rec->assign[pos].ch - 1;
uint8_t idx = rec->assign[pos].ch - 1; if (mLastYD[idx] > actYD)
if (mLastYD[idx] > actYD) mOffYD[idx] += mLastYD[idx];
mOffYD[idx] += mLastYD[idx]; mLastYD[idx] = actYD;
mLastYD[idx] = actYD; rec->record[pos] = mOffYD[idx] + actYD;
rec->record[pos] = mOffYD[idx] + actYD; } else {
} else { if ((REC_TYP)(div) > 1)
if ((REC_TYP)(div) > 1) rec->record[pos] = (REC_TYP)(val) / (REC_TYP)(div);
rec->record[pos] = (REC_TYP)(val) / (REC_TYP)(div); else
else rec->record[pos] = (REC_TYP)(val);
rec->record[pos] = (REC_TYP)(val);
}
} }
} }

7
src/hm/hmSystem.h

@ -16,8 +16,8 @@ class HmSystem {
HmSystem() {} HmSystem() {}
void setup(uint32_t *timestamp, cfgInst_t *config, IApp *app) { void setup(uint32_t *timestamp, cfgInst_t *config, IApp *app) {
mInverter[0].timestamp = timestamp; INVERTERTYPE::timestamp = timestamp;
mInverter[0].generalConfig = config; INVERTERTYPE::generalConfig = config;
//mInverter[0].app = app; //mInverter[0].app = app;
} }
@ -31,11 +31,12 @@ class HmSystem {
if((iv->config->serial.b[5] == 0x11) || (iv->config->serial.b[5] == 0x10)) { if((iv->config->serial.b[5] == 0x11) || (iv->config->serial.b[5] == 0x10)) {
switch(iv->config->serial.b[4]) { switch(iv->config->serial.b[4]) {
case 0x24: // HMS-500 case 0x24: // HMS-500
case 0x25: // HMS-400
case 0x22: case 0x22:
case 0x21: iv->type = INV_TYPE_1CH; case 0x21: iv->type = INV_TYPE_1CH;
break; break;
case 0x25: // HMS-400 - 1 channel but payload like 2ch
case 0x44: // HMS-1000 case 0x44: // HMS-1000
case 0x42: case 0x42:
case 0x41: iv->type = INV_TYPE_2CH; case 0x41: iv->type = INV_TYPE_2CH;

4
src/platformio.ini

@ -191,7 +191,7 @@ monitor_filters =
[env:esp32-wroom32-ethernet] [env:esp32-wroom32-ethernet]
platform = espressif32 platform = espressif32
board = esp32dev board = lolin_d32
lib_deps = lib_deps =
khoih-prog/AsyncWebServer_ESP32_W5500 khoih-prog/AsyncWebServer_ESP32_W5500
khoih-prog/AsyncUDP_ESP32_W5500 khoih-prog/AsyncUDP_ESP32_W5500
@ -214,7 +214,7 @@ monitor_filters =
[env:esp32-wroom32-ethernet-de] [env:esp32-wroom32-ethernet-de]
platform = espressif32 platform = espressif32
board = esp32dev board = lolin_d32
lib_deps = lib_deps =
khoih-prog/AsyncWebServer_ESP32_W5500 khoih-prog/AsyncWebServer_ESP32_W5500
khoih-prog/AsyncUDP_ESP32_W5500 khoih-prog/AsyncUDP_ESP32_W5500

2
src/publisher/pubMqtt.h

@ -423,7 +423,7 @@ class PubMqtt {
} }
DynamicJsonDocument doc2(512); DynamicJsonDocument doc2(512);
constexpr static char* unitTotal[] = {"W", "kWh", "Wh", "W"}; constexpr static const char* unitTotal[] = {"W", "kWh", "Wh", "W"};
doc2[F("name")] = String(name.data()); doc2[F("name")] = String(name.data());
doc2[F("stat_t")] = String(mCfgMqtt->topic) + "/" + ((!total) ? String(iv->config->name) : "total" ) + String(topic.data()); doc2[F("stat_t")] = String(mCfgMqtt->topic) + "/" + ((!total) ? String(iv->config->name) : "total" ) + String(topic.data());
doc2[F("unit_of_meas")] = ((!total) ? (iv->getUnit(mDiscovery.sub, rec)) : (unitTotal[mDiscovery.sub])); doc2[F("unit_of_meas")] = ((!total) ? (iv->getUnit(mDiscovery.sub, rec)) : (unitTotal[mDiscovery.sub]));

2
src/publisher/pubMqttIvData.h

@ -222,7 +222,7 @@ class PubMqttIvData {
mIv->radioStatistics.txCnt, mIv->radioStatistics.txCnt,
mIv->radioStatistics.rxSuccess, mIv->radioStatistics.rxSuccess,
mIv->radioStatistics.rxFail, mIv->radioStatistics.rxFail,
mIv->radioStatistics.rxFailNoAnser, mIv->radioStatistics.rxFailNoAnswer,
mIv->radioStatistics.retransmits, mIv->radioStatistics.retransmits,
mIv->radioStatistics.ivLoss, mIv->radioStatistics.ivLoss,
mIv->radioStatistics.ivSent, mIv->radioStatistics.ivSent,

4
src/utils/scheduler.h

@ -125,8 +125,8 @@ namespace ah {
mTicker[i].timeout = timeout; mTicker[i].timeout = timeout;
mTicker[i].reload = reload; mTicker[i].reload = reload;
mTicker[i].isTimestamp = isTimestamp; mTicker[i].isTimestamp = isTimestamp;
memset(mTicker[i].name, 0, 6); strncpy(mTicker[i].name, name, 5);
strncpy(mTicker[i].name, name, (strlen(name) < 6) ? strlen(name) : 5); mTicker[i].name[5]=0;
if(mMax == i) if(mMax == i)
mMax = i + 1; mMax = i + 1;
return i; return i;

2
src/web/RestApi.h

@ -524,7 +524,7 @@ class RestApi {
obj[F("name")] = String(iv->config->name); obj[F("name")] = String(iv->config->name);
obj[F("rx_success")] = iv->radioStatistics.rxSuccess; obj[F("rx_success")] = iv->radioStatistics.rxSuccess;
obj[F("rx_fail")] = iv->radioStatistics.rxFail; obj[F("rx_fail")] = iv->radioStatistics.rxFail;
obj[F("rx_fail_answer")] = iv->radioStatistics.rxFailNoAnser; obj[F("rx_fail_answer")] = iv->radioStatistics.rxFailNoAnswer;
obj[F("frame_cnt")] = iv->radioStatistics.frmCnt; obj[F("frame_cnt")] = iv->radioStatistics.frmCnt;
obj[F("tx_cnt")] = iv->radioStatistics.txCnt; obj[F("tx_cnt")] = iv->radioStatistics.txCnt;
obj[F("retransmits")] = iv->radioStatistics.retransmits; obj[F("retransmits")] = iv->radioStatistics.retransmits;

4
src/web/html/api.js

@ -84,10 +84,12 @@ function topnav() {
} }
function parseNav(obj) { function parseNav(obj) {
for(i = 0; i < 13; i++) { for(i = 0; i < 14; i++) {
if(i == 2) if(i == 2)
continue; continue;
var l = document.getElementById("nav"+i); var l = document.getElementById("nav"+i);
if(null == l)
continue
if(12 == i) { if(12 == i) {
if(obj.cst_lnk.length > 0) { if(obj.cst_lnk.length > 0) {
l.href = obj.cst_lnk l.href = obj.cst_lnk

11
src/web/html/includes/nav.html

@ -7,18 +7,21 @@
</a> </a>
<div id="topnav" class="mobile"> <div id="topnav" class="mobile">
<a id="nav3" class="hide" href="/live?v={#VERSION}">{#NAV_LIVE}</a> <a id="nav3" class="hide" href="/live?v={#VERSION}">{#NAV_LIVE}</a>
<!--IF_ENABLE_HISTORY-->
<a id="nav11" class="acitve" href="/history?v={#VERSION}">{#NAV_HISTORY}</a> <a id="nav11" class="acitve" href="/history?v={#VERSION}">{#NAV_HISTORY}</a>
<!--ENDIF_ENABLE_HISTORY-->
<a id="nav4" class="hide" href="/serial?v={#VERSION}">{#NAV_WEBSERIAL}</a> <a id="nav4" class="hide" href="/serial?v={#VERSION}">{#NAV_WEBSERIAL}</a>
<a id="nav5" class="hide" href="/setup?v={#VERSION}">{#NAV_SETTINGS}</a> <a id="nav5" class="hide" href="/setup?v={#VERSION}">{#NAV_SETTINGS}</a>
<span class="seperator"></span> <span class="separator"></span>
<a id="nav6" class="hide" href="/update?v={#VERSION}">Update</a> <a id="nav6" class="hide" href="/update?v={#VERSION}">Update</a>
<a id="nav7" class="hide" href="/system?v={#VERSION}">System</a> <a id="nav7" class="hide" href="/system?v={#VERSION}">System</a>
<span class="seperator"></span> <span class="separator"></span>
<a id="nav8" href="/api" target="_blank">REST API</a> <a id="nav8" href="/api" target="_blank">REST API</a>
<a id="nav9" href="https://ahoydtu.de" target="_blank">{#NAV_DOCUMENTATION}</a> <a id="nav9" href="https://docs.ahoydtu.de" target="_blank">{#NAV_DOCUMENTATION}</a>
<a id="nav13" href="https://ahoydtu.de" target="_blank">Website</a>
<a id="nav10" href="/about?v={#VERSION}">{#NAV_ABOUT}</a> <a id="nav10" href="/about?v={#VERSION}">{#NAV_ABOUT}</a>
<a id="nav12" href="#" class="hide" target="_blank">Custom Link</a> <a id="nav12" href="#" class="hide" target="_blank">Custom Link</a>
<span class="seperator"></span> <span class="separator"></span>
<a id="nav0" class="hide" href="/login">Login</a> <a id="nav0" class="hide" href="/login">Login</a>
<a id="nav1" class="hide" href="/logout">Logout</a> <a id="nav1" class="hide" href="/logout">Logout</a>
</div> </div>

116
src/web/html/setup.html

@ -272,7 +272,7 @@
<!--ENDIF_ESP32--> <!--ENDIF_ESP32-->
</fieldset> </fieldset>
</div> </div>
<!--IF_PLUGIN_DISPLAY-->
<button type="button" class="s_collapsible">{#DISPLAY_CONFIG}</button> <button type="button" class="s_collapsible">{#DISPLAY_CONFIG}</button>
<div class="s_content"> <div class="s_content">
<fieldset class="mb-4"> <fieldset class="mb-4">
@ -301,6 +301,7 @@
</div> </div>
</fieldset> </fieldset>
</div> </div>
<!--ENDIF_PLUGIN_DISPLAY-->
<div class="row mb-4 mt-4"> <div class="row mb-4 mt-4">
<div class="col-8 col-sm-3">{#BTN_REBOOT_SUCCESSFUL_SAVE}</div> <div class="col-8 col-sm-3">{#BTN_REBOOT_SUCCESSFUL_SAVE}</div>
@ -341,6 +342,7 @@
var maxInv = 0; var maxInv = 0;
var ts = 0; var ts = 0;
/*IF_ESP8266*/
var esp8266pins = [ var esp8266pins = [
[255, "{#PIN_OFF}"], [255, "{#PIN_OFF}"],
[0, "D3 (GPIO0)"], [0, "D3 (GPIO0)"],
@ -361,6 +363,7 @@
[15, "D8 (GPIO15)"], [15, "D8 (GPIO15)"],
[16, "D0 (GPIO16 - {#PIN_NO_IRQ})"] [16, "D0 (GPIO16 - {#PIN_NO_IRQ})"]
]; ];
/*ENDIF_ESP8266*/
/*IF_ESP32*/ /*IF_ESP32*/
var esp32pins = [ var esp32pins = [
@ -392,6 +395,7 @@
[36, "VP (GPIO36, {#PIN_INPUT_ONLY})"], [36, "VP (GPIO36, {#PIN_INPUT_ONLY})"],
[39, "VN (GPIO39, {#PIN_INPUT_ONLY})"] [39, "VN (GPIO39, {#PIN_INPUT_ONLY})"]
]; ];
/*IF_ESP32-S2*/
var esp32sXpins = [ var esp32sXpins = [
[255, "off / default"], [255, "off / default"],
[0, "GPIO0 ({#PIN_DONT_USE} - BOOT)"], [0, "GPIO0 ({#PIN_DONT_USE} - BOOT)"],
@ -440,6 +444,58 @@
[47, "GPIO47"], [47, "GPIO47"],
[48, "GPIO48"], [48, "GPIO48"],
]; ];
/*ENDIF_ESP32-S2*/
/*IF_ESP32-S3*/
var esp32sXpins = [
[255, "off / default"],
[0, "GPIO0 ({#PIN_DONT_USE} - BOOT)"],
[1, "GPIO1"],
[2, "GPIO2"],
[3, "GPIO3"],
[4, "GPIO4"],
[5, "GPIO5"],
[6, "GPIO6"],
[7, "GPIO7"],
[8, "GPIO8"],
[9, "GPIO9"],
[10, "GPIO10"],
[11, "GPIO11"],
[12, "GPIO12"],
[13, "GPIO13"],
[14, "GPIO14"],
[15, "GPIO15"],
[16, "GPIO16"],
[17, "GPIO17"],
[18, "GPIO18"],
[19, "GPIO19 ({#PIN_DONT_USE} - USB-)"],
[20, "GPIO20 ({#PIN_DONT_USE} - USB+)"],
[21, "GPIO21"],
[26, "GPIO26 (PSRAM - {#PIN_NOT_AVAIL})"],
[27, "GPIO27 (FLASH - {#PIN_NOT_AVAIL})"],
[28, "GPIO28 (FLASH - {#PIN_NOT_AVAIL})"],
[29, "GPIO29 (FLASH - {#PIN_NOT_AVAIL})"],
[30, "GPIO30 (FLASH - {#PIN_NOT_AVAIL})"],
[31, "GPIO31 (FLASH - {#PIN_NOT_AVAIL})"],
[32, "GPIO32 (FLASH - {#PIN_NOT_AVAIL})"],
[33, "GPIO33 (not exposed on S3-WROOM modules)"],
[34, "GPIO34 (not exposed on S3-WROOM modules)"],
[35, "GPIO35"],
[36, "GPIO36"],
[37, "GPIO37"],
[38, "GPIO38"],
[39, "GPIO39"],
[40, "GPIO40"],
[41, "GPIO41"],
[42, "GPIO42"],
[43, "GPIO43"],
[44, "GPIO44"],
[45, "GPIO45 ({#PIN_DONT_USE} - STRAPPING PIN)"],
[46, "GPIO46 ({#PIN_DONT_USE} - STRAPPING PIN)"],
[47, "GPIO47"],
[48, "GPIO48"],
];
/*ENDIF_ESP32-S3*/
/*IF_ESP32-C3*/
var esp32c3pins = [ var esp32c3pins = [
[255, "off / default"], [255, "off / default"],
[0, "GPIO0"], [0, "GPIO0"],
@ -465,6 +521,7 @@
[20, "GPIO20 (RX)"], [20, "GPIO20 (RX)"],
[21, "GPIO21 (TX)"], [21, "GPIO21 (TX)"],
]; ];
/*ENDIF_ESP32-C3*/
/*ENDIF_ESP32*/ /*ENDIF_ESP32*/
var nrfPa = [ var nrfPa = [
[0, "MIN ({#PIN_RECOMMENDED})"], [0, "MIN ({#PIN_RECOMMENDED})"],
@ -890,11 +947,19 @@
function parsePinout(obj, type, system) { function parsePinout(obj, type, system) {
var e = document.getElementById("pinout"); var e = document.getElementById("pinout");
var pinList = esp8266pins;
/*IF_ESP32*/ /*IF_ESP32*/
var pinList = esp32pins; var pinList = esp32pins;
if ("ESP32-S3" == system.chip_model || "ESP32-S2" == system.chip_model) pinList = esp32sXpins; /*IF_ESP32-S2*/
else if("ESP32-C3" == system["chip_model"]) pinList = esp32c3pins; pinList = esp32sXpins;
/*ENDIF_ESP32-S2*/
/*IF_ESP32-S3*/
pinList = esp32sXpins;
/*ENDIF_ESP32-S3*/
/*IF_ESP32-C3*/
pinList = esp32c3pins;
/*ENDIF_ESP32-C3*/
/*ELSE*/
var pinList = esp8266pins;
/*ENDIF_ESP32*/ /*ENDIF_ESP32*/
pins = [['led0', 'pinLed0', '{#LED_AT_LEAST_ONE_PRODUCING}'], ['led1', 'pinLed1', '{#LED_MQTT_CONNECTED}'], ['led2', 'pinLed2', '{#LED_NIGHT_TIME}']]; pins = [['led0', 'pinLed0', '{#LED_AT_LEAST_ONE_PRODUCING}'], ['led1', 'pinLed1', '{#LED_MQTT_CONNECTED}'], ['led2', 'pinLed2', '{#LED_NIGHT_TIME}']];
for(p of pins) { for(p of pins) {
@ -926,11 +991,19 @@
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 = esp8266pins;
/*IF_ESP32*/ /*IF_ESP32*/
var pinList = esp32pins; var pinList = esp32pins;
if ("ESP32-S3" == system.chip_model || "ESP32-S2" == system.chip_model) pinList = esp32sXpins; /*IF_ESP32-S2*/
else if("ESP32-C3" == system["chip_model"]) pinList = esp32c3pins; pinList = esp32sXpins;
/*ENDIF_ESP32-S2*/
/*IF_ESP32-S3*/
pinList = esp32sXpins;
/*ENDIF_ESP32-S3*/
/*IF_ESP32-C3*/
pinList = esp32c3pins;
/*ENDIF_ESP32-C3*/
/*ELSE*/
var pinList = esp8266pins;
/*ENDIF_ESP32*/ /*ENDIF_ESP32*/
e.replaceChildren ( e.replaceChildren (
@ -962,8 +1035,15 @@
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; var pinList = esp32pins;
if ("ESP32-S3" == system.chip_model || "ESP32-S2" == system.chip_model) pinList = esp32sXpins; /*IF_ESP32-S2*/
else if("ESP32-C3" == system["chip_model"]) pinList = esp32c3pins; pinList = esp32sXpins;
/*ENDIF_ESP32-S2*/
/*IF_ESP32-S3*/
pinList = esp32sXpins;
/*ENDIF_ESP32-S3*/
/*IF_ESP32-C3*/
pinList = esp32c3pins;
/*ENDIF_ESP32-C3*/
en.checked = obj["en"]; en.checked = obj["en"];
@ -1008,12 +1088,21 @@
} }
} }
/*IF_PLUGIN_DISPLAY*/
function parseDisplay(obj, type, system) { function parseDisplay(obj, type, system) {
var pinList = esp8266pins;
/*IF_ESP32*/ /*IF_ESP32*/
var pinList = esp32pins; var pinList = esp32pins;
if ("ESP32-S3" == system.chip_model || "ESP32-S2" == system.chip_model) pinList = esp32sXpins; /*IF_ESP32-S2*/
else if("ESP32-C3" == system["chip_model"]) pinList = esp32c3pins; pinList = esp32sXpins;
/*ENDIF_ESP32-S2*/
/*IF_ESP32-S3*/
pinList = esp32sXpins;
/*ENDIF_ESP32-S3*/
/*IF_ESP32-C3*/
pinList = esp32c3pins;
/*ENDIF_ESP32-C3*/
/*ELSE*/
var pinList = esp8266pins;
/*ENDIF_ESP32*/ /*ENDIF_ESP32*/
for(var i of ["disp_pwr"]) for(var i of ["disp_pwr"])
@ -1149,6 +1238,7 @@
setHide("screenSaver", !optionsMap.get(dispType)[2]); setHide("screenSaver", !optionsMap.get(dispType)[2]);
setHide("pirPin", !(optionsMap.get(dispType)[2] && (screenSaver==2))); // show pir pin only for motion screensaver setHide("pirPin", !(optionsMap.get(dispType)[2] && (screenSaver==2))); // show pir pin only for motion screensaver
} }
/*ENDIF_PLUGIN_DISPLAY*/
function tick() { function tick() {
document.getElementById("date").innerHTML = toIsoDateStr((new Date((++ts) * 1000))); document.getElementById("date").innerHTML = toIsoDateStr((new Date((++ts) * 1000)));
@ -1168,7 +1258,9 @@
parseCmtRadio(root["radioCmt"], root["system"]["esp_type"], root["system"]); parseCmtRadio(root["radioCmt"], root["system"]["esp_type"], root["system"]);
/*ENDIF_ESP32*/ /*ENDIF_ESP32*/
parseSerial(root["serial"]); parseSerial(root["serial"]);
/*IF_PLUGIN_DISPLAY*/
parseDisplay(root["display"], root["system"]["esp_type"], root["system"]); parseDisplay(root["display"], root["system"]["esp_type"], root["system"]);
/*ENDIF_PLUGIN_DISPLAY*/
getAjax("/api/inverter/list", parseIv); getAjax("/api/inverter/list", parseIv);
} }
} }

2
src/web/html/style.css

@ -153,7 +153,7 @@ svg.icon {
background-color: var(--nav-active); background-color: var(--nav-active);
} }
span.seperator { span.separator {
width: 100%; width: 100%;
height: 1px; height: 1px;
margin: 5px 0 5px; margin: 5px 0 5px;

2
src/web/web.h

@ -661,7 +661,7 @@ class Web {
{ "max_power", "gauge", metricConstInverterFormat, [](Inverter<> *iv)-> uint64_t {return iv->getMaxPower();} }, { "max_power", "gauge", metricConstInverterFormat, [](Inverter<> *iv)-> uint64_t {return iv->getMaxPower();} },
{ "radio_rx_success", "counter" ,metricConstInverterFormat, [](Inverter<> *iv)-> uint64_t {return iv->radioStatistics.rxSuccess;} }, { "radio_rx_success", "counter" ,metricConstInverterFormat, [](Inverter<> *iv)-> uint64_t {return iv->radioStatistics.rxSuccess;} },
{ "radio_rx_fail", "counter" ,metricConstInverterFormat, [](Inverter<> *iv)-> uint64_t {return iv->radioStatistics.rxFail;} }, { "radio_rx_fail", "counter" ,metricConstInverterFormat, [](Inverter<> *iv)-> uint64_t {return iv->radioStatistics.rxFail;} },
{ "radio_rx_fail_answer", "counter" ,metricConstInverterFormat, [](Inverter<> *iv)-> uint64_t {return iv->radioStatistics.rxFailNoAnser;} }, { "radio_rx_fail_answer", "counter" ,metricConstInverterFormat, [](Inverter<> *iv)-> uint64_t {return iv->radioStatistics.rxFailNoAnswer;} },
{ "radio_frame_cnt", "counter" ,metricConstInverterFormat, [](Inverter<> *iv)-> uint64_t {return iv->radioStatistics.frmCnt;} }, { "radio_frame_cnt", "counter" ,metricConstInverterFormat, [](Inverter<> *iv)-> uint64_t {return iv->radioStatistics.frmCnt;} },
{ "radio_tx_cnt", "counter" ,metricConstInverterFormat, [](Inverter<> *iv)-> uint64_t {return iv->radioStatistics.txCnt;} }, { "radio_tx_cnt", "counter" ,metricConstInverterFormat, [](Inverter<> *iv)-> uint64_t {return iv->radioStatistics.txCnt;} },
{ "radio_retransmits", "counter" ,metricConstInverterFormat, [](Inverter<> *iv)-> uint64_t {return iv->radioStatistics.retransmits;} }, { "radio_retransmits", "counter" ,metricConstInverterFormat, [](Inverter<> *iv)-> uint64_t {return iv->radioStatistics.retransmits;} },

Loading…
Cancel
Save