Browse Source

0.7.31

* fixed docu #1085
* changed active power limit MqTT messages to QOS2 #1072
* improved alarm messages, added alarm-id to log #1089
* trigger power limit read on next day (if inverter was offline meanwhile)
* disabled improv implementation to check if it is related to 'Schwuppdizitaet'
* changed live view to gray once inverter isn't available
* added inverter status to API
* changed sum of totals on WebGui depending on inverter status #1084
* merge maximum power (AC and DC) from PR #1080
pull/1093/head
lumapu 1 year ago
parent
commit
55764102ce
  1. 2
      User_Manual.md
  2. 11
      src/CHANGES.md
  3. 4
      src/app.cpp
  4. 2
      src/app.h
  5. 2
      src/defines.h
  6. 42
      src/hm/hmDefines.h
  7. 85
      src/hm/hmInverter.h
  8. 1
      src/hm/hmPayload.h
  9. 2
      src/hm/hmRadio.h
  10. 93
      src/hms/hmsDefines.h
  11. 4
      src/hms/hmsRadio.h
  12. 20
      src/publisher/pubMqtt.h
  13. 2
      src/publisher/pubMqttDefs.h
  14. 12
      src/publisher/pubMqttIvData.h
  15. 12
      src/web/RestApi.h
  16. 2
      src/web/html/colorBright.css
  17. 2
      src/web/html/colorDark.css
  18. 1
      src/web/html/index.html
  19. 10
      src/web/html/style.css
  20. 30
      src/web/html/visualization.html

2
User_Manual.md

@ -168,7 +168,7 @@ This feature was removed. The persisten limit should not be modified cyclic by a
### Generic Information
The rest API works with *JSON* POST requests. All the following instructions must be sent to the `/api` endpoint of the AhoyDTU.
The rest API works with *JSON* POST requests. All the following instructions must be sent to the `/api/ctrl` endpoint of the AhoyDTU.
👆 `<INVERTER_ID>` is the number of the specific inverter in the setup page.

11
src/CHANGES.md

@ -1,5 +1,16 @@
# Development Changes
## 0.7.31 - 2023-08-13
* fixed docu #1085
* changed active power limit MqTT messages to QOS2 #1072
* improved alarm messages, added alarm-id to log #1089
* trigger power limit read on next day (if inverter was offline meanwhile)
* disabled improv implementation to check if it is related to 'Schwuppdizitaet'
* changed live view to gray once inverter isn't available
* added inverter status to API
* changed sum of totals on WebGui depending on inverter status #1084
* merge maximum power (AC and DC) from PR #1080
## 0.7.30 - 2023-08-10
* attempt to improve speed / repsonse times (Schwuppdizitaet) #1075

4
src/app.cpp

@ -120,7 +120,7 @@ void app::setup() {
mPubSerial.setup(mConfig, &mSys, &mTimestamp);
#if !defined(ETHERNET)
mImprov.setup(this, mConfig->sys.deviceName, mVersion);
//mImprov.setup(this, mConfig->sys.deviceName, mVersion);
#endif
regularTickers();
@ -248,7 +248,7 @@ void app::regularTickers(void) {
everySec(std::bind(&DisplayType::tickerSecond, &mDisplay), "disp");
every(std::bind(&PubSerialType::tick, &mPubSerial), mConfig->serial.interval, "uart");
#if !defined(ETHERNET)
everySec([this]() { mImprov.tickSerial(); }, "impro");
//everySec([this]() { mImprov.tickSerial(); }, "impro");
#endif
// every([this]() { mPayload.simulation();}, 15, "simul");
}

2
src/app.h

@ -332,7 +332,7 @@ class app : public IApp, public ah::Scheduler {
MiPayloadType mMiPayload;
PubSerialType mPubSerial;
#if !defined(ETHERNET)
Improv mImprov;
//Improv mImprov;
#endif
#ifdef ESP32
CmtRadioType mCmtRadio;

2
src/defines.h

@ -13,7 +13,7 @@
//-------------------------------------
#define VERSION_MAJOR 0
#define VERSION_MINOR 7
#define VERSION_PATCH 30
#define VERSION_PATCH 31
//-------------------------------------
typedef struct {

42
src/hm/hmDefines.h

@ -22,19 +22,19 @@ enum {FLD_UDC = 0, FLD_IDC, FLD_PDC, FLD_YD, FLD_YW, FLD_YT,
FLD_IAC_1, FLD_IAC_2, FLD_IAC_3, FLD_PAC, FLD_F, FLD_T, FLD_PF, FLD_EFF,
FLD_IRR, FLD_Q, FLD_EVT, FLD_FW_VERSION, FLD_FW_BUILD_YEAR,
FLD_FW_BUILD_MONTH_DAY, FLD_FW_BUILD_HOUR_MINUTE, FLD_HW_ID,
FLD_ACT_ACTIVE_PWR_LIMIT, /*FLD_ACT_REACTIVE_PWR_LIMIT, FLD_ACT_PF,*/ FLD_LAST_ALARM_CODE};
FLD_ACT_ACTIVE_PWR_LIMIT, /*FLD_ACT_REACTIVE_PWR_LIMIT, FLD_ACT_PF,*/ FLD_LAST_ALARM_CODE, FLD_MP};
const char* const fields[] = {"U_DC", "I_DC", "P_DC", "YieldDay", "YieldWeek", "YieldTotal",
"U_AC", "U_AC_1N", "U_AC_2N", "U_AC_3N", "UAC_12", "UAC_23", "UAC_31", "I_AC",
"IAC_1", "I_AC_2", "I_AC_3", "P_AC", "F_AC", "Temp", "PF_AC", "Efficiency", "Irradiation","Q_AC",
"ALARM_MES_ID","FWVersion","FWBuildYear","FWBuildMonthDay","FWBuildHourMinute","HWPartId",
"active_PowerLimit", /*"reactivePowerLimit","Powerfactor",*/ "LastAlarmCode"};
"active_PowerLimit", /*"reactivePowerLimit","Powerfactor",*/ "LastAlarmCode", "MaxPower"};
const char* const notAvail = "n/a";
const uint8_t fieldUnits[] = {UNIT_V, UNIT_A, UNIT_W, UNIT_WH, UNIT_KWH, UNIT_KWH,
UNIT_V, UNIT_V, UNIT_V, UNIT_V, UNIT_V, UNIT_V, UNIT_V, UNIT_A, UNIT_A, UNIT_A, UNIT_A,
UNIT_W, UNIT_HZ, UNIT_C, UNIT_NONE, UNIT_PCT, UNIT_PCT, UNIT_VAR,
UNIT_NONE, UNIT_NONE, UNIT_NONE, UNIT_NONE, UNIT_NONE, UNIT_NONE, UNIT_PCT, UNIT_NONE};
UNIT_NONE, UNIT_NONE, UNIT_NONE, UNIT_NONE, UNIT_NONE, UNIT_NONE, UNIT_PCT, UNIT_NONE, UNIT_W};
// mqtt discovery device classes
enum {DEVICE_CLS_NONE = 0, DEVICE_CLS_CURRENT, DEVICE_CLS_ENERGY, DEVICE_CLS_PWR, DEVICE_CLS_VOLTAGE, DEVICE_CLS_FREQ, DEVICE_CLS_TEMP};
@ -65,7 +65,7 @@ const byteAssign_fieldDeviceClass deviceFieldAssignment[] = {
#define DEVICE_CLS_ASSIGN_LIST_LEN (sizeof(deviceFieldAssignment) / sizeof(byteAssign_fieldDeviceClass))
// indices to calculation functions, defined in hmInverter.h
enum {CALC_YT_CH0 = 0, CALC_YD_CH0, CALC_UDC_CH, CALC_PDC_CH0, CALC_EFF_CH0, CALC_IRR_CH};
enum {CALC_YT_CH0 = 0, CALC_YD_CH0, CALC_UDC_CH, CALC_PDC_CH0, CALC_EFF_CH0, CALC_IRR_CH, CALC_MPAC_CH0, CALC_MPDC_CH};
enum {CMD_CALC = 0xffff};
@ -129,6 +129,7 @@ const byteAssign_t hm1chAssignment[] = {
{ FLD_YD, UNIT_WH, CH1, 12, 2, 1 },
{ FLD_YT, UNIT_KWH, CH1, 8, 4, 1000 },
{ FLD_IRR, UNIT_PCT, CH1, CALC_IRR_CH, CH1, CMD_CALC },
{ FLD_MP, UNIT_W, CH1, CALC_MPDC_CH, CH1, CMD_CALC },
{ FLD_UAC, UNIT_V, CH0, 14, 2, 10 },
{ FLD_IAC, UNIT_A, CH0, 22, 2, 100 },
@ -138,10 +139,11 @@ const byteAssign_t hm1chAssignment[] = {
{ FLD_PF, UNIT_NONE, CH0, 24, 2, 1000 },
{ FLD_T, UNIT_C, CH0, 26, 2, 10 },
{ FLD_EVT, UNIT_NONE, CH0, 28, 2, 1 },
{ FLD_YD, UNIT_WH, CH0, CALC_YD_CH0, 0, CMD_CALC },
{ FLD_YT, UNIT_KWH, CH0, CALC_YT_CH0, 0, CMD_CALC },
{ FLD_PDC, UNIT_W, CH0, CALC_PDC_CH0, 0, CMD_CALC },
{ FLD_EFF, UNIT_PCT, CH0, CALC_EFF_CH0, 0, CMD_CALC }
{ FLD_YD, UNIT_WH, CH0, CALC_YD_CH0, 0, CMD_CALC },
{ FLD_YT, UNIT_KWH, CH0, CALC_YT_CH0, 0, CMD_CALC },
{ FLD_PDC, UNIT_W, CH0, CALC_PDC_CH0, 0, CMD_CALC },
{ FLD_EFF, UNIT_PCT, CH0, CALC_EFF_CH0, 0, CMD_CALC },
{ FLD_MP, UNIT_W, CH0, CALC_MPAC_CH0, 0, CMD_CALC }
};
#define HM1CH_LIST_LEN (sizeof(hm1chAssignment) / sizeof(byteAssign_t))
#define HM1CH_PAYLOAD_LEN 30
@ -157,6 +159,7 @@ const byteAssign_t hm2chAssignment[] = {
{ FLD_YD, UNIT_WH, CH1, 22, 2, 1 },
{ FLD_YT, UNIT_KWH, CH1, 14, 4, 1000 },
{ FLD_IRR, UNIT_PCT, CH1, CALC_IRR_CH, CH1, CMD_CALC },
{ FLD_MP, UNIT_W, CH1, CALC_MPDC_CH, CH1, CMD_CALC },
{ FLD_UDC, UNIT_V, CH2, 8, 2, 10 },
{ FLD_IDC, UNIT_A, CH2, 10, 2, 100 },
@ -164,6 +167,7 @@ const byteAssign_t hm2chAssignment[] = {
{ FLD_YD, UNIT_WH, CH2, 24, 2, 1 },
{ FLD_YT, UNIT_KWH, CH2, 18, 4, 1000 },
{ FLD_IRR, UNIT_PCT, CH2, CALC_IRR_CH, CH2, CMD_CALC },
{ FLD_MP, UNIT_W, CH2, CALC_MPDC_CH, CH2, CMD_CALC },
{ FLD_UAC, UNIT_V, CH0, 26, 2, 10 },
{ FLD_IAC, UNIT_A, CH0, 34, 2, 100 },
@ -173,10 +177,11 @@ const byteAssign_t hm2chAssignment[] = {
{ FLD_PF, UNIT_NONE, CH0, 36, 2, 1000 },
{ FLD_T, UNIT_C, CH0, 38, 2, 10 },
{ FLD_EVT, UNIT_NONE, CH0, 40, 2, 1 },
{ FLD_YD, UNIT_WH, CH0, CALC_YD_CH0, 0, CMD_CALC },
{ FLD_YT, UNIT_KWH, CH0, CALC_YT_CH0, 0, CMD_CALC },
{ FLD_PDC, UNIT_W, CH0, CALC_PDC_CH0, 0, CMD_CALC },
{ FLD_EFF, UNIT_PCT, CH0, CALC_EFF_CH0, 0, CMD_CALC }
{ FLD_YD, UNIT_WH, CH0, CALC_YD_CH0, 0, CMD_CALC },
{ FLD_YT, UNIT_KWH, CH0, CALC_YT_CH0, 0, CMD_CALC },
{ FLD_PDC, UNIT_W, CH0, CALC_PDC_CH0, 0, CMD_CALC },
{ FLD_EFF, UNIT_PCT, CH0, CALC_EFF_CH0, 0, CMD_CALC },
{ FLD_MP, UNIT_W, CH0, CALC_MPAC_CH0, 0, CMD_CALC }
};
#define HM2CH_LIST_LEN (sizeof(hm2chAssignment) / sizeof(byteAssign_t))
@ -193,6 +198,7 @@ const byteAssign_t hm4chAssignment[] = {
{ FLD_YD, UNIT_WH, CH1, 20, 2, 1 },
{ FLD_YT, UNIT_KWH, CH1, 12, 4, 1000 },
{ FLD_IRR, UNIT_PCT, CH1, CALC_IRR_CH, CH1, CMD_CALC },
{ FLD_MP, UNIT_W, CH1, CALC_MPDC_CH, CH1, CMD_CALC },
{ FLD_UDC, UNIT_V, CH2, CALC_UDC_CH, CH1, CMD_CALC },
{ FLD_IDC, UNIT_A, CH2, 6, 2, 100 },
@ -200,6 +206,7 @@ const byteAssign_t hm4chAssignment[] = {
{ FLD_YD, UNIT_WH, CH2, 22, 2, 1 },
{ FLD_YT, UNIT_KWH, CH2, 16, 4, 1000 },
{ FLD_IRR, UNIT_PCT, CH2, CALC_IRR_CH, CH2, CMD_CALC },
{ FLD_MP, UNIT_W, CH2, CALC_MPDC_CH, CH2, CMD_CALC },
{ FLD_UDC, UNIT_V, CH3, 24, 2, 10 },
{ FLD_IDC, UNIT_A, CH3, 26, 2, 100 },
@ -207,6 +214,7 @@ const byteAssign_t hm4chAssignment[] = {
{ FLD_YD, UNIT_WH, CH3, 42, 2, 1 },
{ FLD_YT, UNIT_KWH, CH3, 34, 4, 1000 },
{ FLD_IRR, UNIT_PCT, CH3, CALC_IRR_CH, CH3, CMD_CALC },
{ FLD_MP, UNIT_W, CH3, CALC_MPDC_CH, CH3, CMD_CALC },
{ FLD_UDC, UNIT_V, CH4, CALC_UDC_CH, CH3, CMD_CALC },
{ FLD_IDC, UNIT_A, CH4, 28, 2, 100 },
@ -214,6 +222,7 @@ const byteAssign_t hm4chAssignment[] = {
{ FLD_YD, UNIT_WH, CH4, 44, 2, 1 },
{ FLD_YT, UNIT_KWH, CH4, 38, 4, 1000 },
{ FLD_IRR, UNIT_PCT, CH4, CALC_IRR_CH, CH4, CMD_CALC },
{ FLD_MP, UNIT_W, CH4, CALC_MPDC_CH, CH4, CMD_CALC },
{ FLD_UAC, UNIT_V, CH0, 46, 2, 10 },
{ FLD_IAC, UNIT_A, CH0, 54, 2, 100 },
@ -223,10 +232,11 @@ const byteAssign_t hm4chAssignment[] = {
{ FLD_PF, UNIT_NONE, CH0, 56, 2, 1000 },
{ FLD_T, UNIT_C, CH0, 58, 2, 10 },
{ FLD_EVT, UNIT_NONE, CH0, 60, 2, 1 },
{ FLD_YD, UNIT_WH, CH0, CALC_YD_CH0, 0, CMD_CALC },
{ FLD_YT, UNIT_KWH, CH0, CALC_YT_CH0, 0, CMD_CALC },
{ FLD_PDC, UNIT_W, CH0, CALC_PDC_CH0, 0, CMD_CALC },
{ FLD_EFF, UNIT_PCT, CH0, CALC_EFF_CH0, 0, CMD_CALC }
{ FLD_YD, UNIT_WH, CH0, CALC_YD_CH0, 0, CMD_CALC },
{ FLD_YT, UNIT_KWH, CH0, CALC_YT_CH0, 0, CMD_CALC },
{ FLD_PDC, UNIT_W, CH0, CALC_PDC_CH0, 0, CMD_CALC },
{ FLD_EFF, UNIT_PCT, CH0, CALC_EFF_CH0, 0, CMD_CALC },
{ FLD_MP, UNIT_W, CH0, CALC_MPAC_CH0, 0, CMD_CALC }
};
#define HM4CH_LIST_LEN (sizeof(hm4chAssignment) / sizeof(byteAssign_t))
#define HM4CH_PAYLOAD_LEN 62

85
src/hm/hmInverter.h

@ -48,6 +48,12 @@ static T calcEffiencyCh0(Inverter<> *iv, uint8_t arg0);
template<class T=float>
static T calcIrradiation(Inverter<> *iv, uint8_t arg0);
template<class T=float>
static T calcMaxPowerAcCh0(Inverter<> *iv, uint8_t arg0);
template<class T=float>
static T calcMaxPowerDc(Inverter<> *iv, uint8_t arg0);
template<class T=float>
using func_t = T (Inverter<> *, uint8_t);
@ -102,12 +108,14 @@ class InfoCommand : public CommandAbstract {
// list of all available functions, mapped in hmDefines.h
template<class T=float>
const calcFunc_t<T> calcFunctions[] = {
{ CALC_YT_CH0, &calcYieldTotalCh0 },
{ CALC_YD_CH0, &calcYieldDayCh0 },
{ CALC_UDC_CH, &calcUdcCh },
{ CALC_PDC_CH0, &calcPowerDcCh0 },
{ CALC_EFF_CH0, &calcEffiencyCh0 },
{ CALC_IRR_CH, &calcIrradiation }
{ CALC_YT_CH0, &calcYieldTotalCh0 },
{ CALC_YD_CH0, &calcYieldDayCh0 },
{ CALC_UDC_CH, &calcUdcCh },
{ CALC_PDC_CH0, &calcPowerDcCh0 },
{ CALC_EFF_CH0, &calcEffiencyCh0 },
{ CALC_IRR_CH, &calcIrradiation },
{ CALC_MPAC_CH0, &calcMaxPowerAcCh0 },
{ CALC_MPDC_CH, &calcMaxPowerDc }
};
enum class InverterStatus : uint8_t {
@ -314,8 +322,8 @@ class Inverter {
DPRINTLN(DBG_VERBOSE, "add real time");
// get last alarm message index and save it in the inverter object
if (getPosByChFld(0, FLD_EVT, rec) == pos){
if (alarmMesIndex < rec->record[pos]){
if (getPosByChFld(0, FLD_EVT, rec) == pos) {
if (alarmMesIndex < rec->record[pos]) {
alarmMesIndex = rec->record[pos];
//enqueCommand<InfoCommand>(AlarmUpdate); // What is the function of AlarmUpdate?
@ -415,8 +423,10 @@ class Inverter {
if(status < InverterStatus::PRODUCING)
status = InverterStatus::STARTING;
} else {
if((*timestamp - recordMeas.ts) > INVERTER_OFF_THRES_SEC)
if((*timestamp - recordMeas.ts) > INVERTER_OFF_THRES_SEC) {
status = InverterStatus::OFF;
actPowerLimit = 0xffff; // power limit will be read once inverter becomes available
}
else
status = InverterStatus::WAS_ON;
}
@ -680,8 +690,7 @@ static T calcYieldTotalCh0(Inverter<> *iv, uint8_t arg0) {
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug);
T yield = 0;
for(uint8_t i = 1; i <= iv->channels; i++) {
uint8_t pos = iv->getPosByChFld(i, FLD_YT, rec);
yield += iv->getValue(pos, rec);
yield += iv->getChannelFieldValue(i, FLD_YT, rec);
}
return yield;
}
@ -695,8 +704,7 @@ static T calcYieldDayCh0(Inverter<> *iv, uint8_t arg0) {
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug);
T yield = 0;
for(uint8_t i = 1; i <= iv->channels; i++) {
uint8_t pos = iv->getPosByChFld(i, FLD_YD, rec);
yield += iv->getValue(pos, rec);
yield += iv->getChannelFieldValue(i, FLD_YD, rec);
}
return yield;
}
@ -724,8 +732,7 @@ static T calcPowerDcCh0(Inverter<> *iv, uint8_t arg0) {
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug);
T dcPower = 0;
for(uint8_t i = 1; i <= iv->channels; i++) {
uint8_t pos = iv->getPosByChFld(i, FLD_PDC, rec);
dcPower += iv->getValue(pos, rec);
dcPower += iv->getChannelFieldValue(i, FLD_PDC, rec);
}
return dcPower;
}
@ -737,12 +744,10 @@ static T calcEffiencyCh0(Inverter<> *iv, uint8_t arg0) {
DPRINTLN(DBG_VERBOSE, F("hmInverter.h:calcEfficiencyCh0"));
if(NULL != iv) {
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug);
uint8_t pos = iv->getPosByChFld(CH0, FLD_PAC, rec);
T acPower = iv->getValue(pos, rec);
T acPower = iv->getChannelFieldValue(CH0, FLD_PAC, rec);
T dcPower = 0;
for(uint8_t i = 1; i <= iv->channels; i++) {
pos = iv->getPosByChFld(i, FLD_PDC, rec);
dcPower += iv->getValue(pos, rec);
dcPower += iv->getChannelFieldValue(i, FLD_PDC, rec);
}
if(dcPower > 0)
return acPower / dcPower * 100.0f;
@ -756,11 +761,49 @@ static T calcIrradiation(Inverter<> *iv, uint8_t arg0) {
// arg0 = channel
if(NULL != iv) {
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug);
uint8_t pos = iv->getPosByChFld(arg0, FLD_PDC, rec);
if(iv->config->chMaxPwr[arg0-1] > 0)
return iv->getValue(pos, rec) / iv->config->chMaxPwr[arg0-1] * 100.0f;
return iv->getChannelFieldValue(arg0, FLD_PDC, rec) / iv->config->chMaxPwr[arg0-1] * 100.0f;
}
return 0.0;
}
template<class T=float>
static T calcMaxPowerAcCh0(Inverter<> *iv, uint8_t arg0) {
DPRINTLN(DBG_VERBOSE, F("hmInverter.h:calcMaxPowerAcCh0"));
T acMaxPower = 0.0;
if(NULL != iv) {
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug);
T acPower = iv->getChannelFieldValue(arg0, FLD_PAC, rec);
for(uint8_t i = 0; i < rec->length; i++) {
if((FLD_MP == rec->assign[i].fieldId) && (0 == rec->assign[i].ch)) {
acMaxPower = iv->getValue(i, rec);
}
}
if(acPower > acMaxPower)
return acPower;
}
return acMaxPower;
}
template<class T=float>
static T calcMaxPowerDc(Inverter<> *iv, uint8_t arg0) {
DPRINTLN(DBG_VERBOSE, F("hmInverter.h:calcMaxPowerDc"));
// arg0 = channel
T dcMaxPower = 0.0;
if(NULL != iv) {
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug);
T dcPower = iv->getChannelFieldValue(arg0, FLD_PDC, rec);
for(uint8_t i = 0; i < rec->length; i++) {
if((FLD_MP == rec->assign[i].fieldId) && (arg0 == rec->assign[i].ch)) {
dcMaxPower = iv->getValue(i, rec);
}
}
if(dcPower > dcMaxPower)
return dcPower;
}
return dcMaxPower;
}
#endif /*__HM_INVERTER_H__*/

1
src/hm/hmPayload.h

@ -326,7 +326,6 @@ class HmPayload {
if(AlarmData == mPayload[iv->id].txCmd) {
uint8_t i = 0;
uint32_t start, end;
while(1) {
if(0 == iv->parseAlarmLog(i++, payload, payloadLen))
break;

2
src/hm/hmRadio.h

@ -217,7 +217,7 @@ class HmRadio {
mTxBuf[10] = cmd; // cid
mTxBuf[11] = 0x00;
CP_U32_LittleEndian(&mTxBuf[12], ts);
if (cmd == RealTimeRunData_Debug || cmd == AlarmData ) {
if (cmd == AlarmData ) { //cmd == RealTimeRunData_Debug ||
mTxBuf[18] = (alarmMesId >> 8) & 0xff;
mTxBuf[19] = (alarmMesId ) & 0xff;
}

93
src/hms/hmsDefines.h

@ -18,6 +18,7 @@ const byteAssign_t hms1chAssignment[] = {
{ FLD_YT, UNIT_KWH, CH1, 8, 4, 1000 },
{ FLD_YD, UNIT_WH, CH1, 12, 2, 1 },
{ FLD_IRR, UNIT_PCT, CH1, CALC_IRR_CH, CH1, CMD_CALC },
{ FLD_MP, UNIT_W, CH1, CALC_MPDC_CH, CH1, CMD_CALC },
{ FLD_UAC, UNIT_V, CH0, 14, 2, 10 },
{ FLD_F, UNIT_HZ, CH0, 16, 2, 100 },
@ -28,10 +29,11 @@ const byteAssign_t hms1chAssignment[] = {
{ FLD_T, UNIT_C, CH0, 26, 2, 10 }, // signed!
{ FLD_EVT, UNIT_NONE, CH0, 28, 2, 1 },
{ FLD_YD, UNIT_WH, CH0, CALC_YD_CH0, 0, CMD_CALC },
{ FLD_YT, UNIT_KWH, CH0, CALC_YT_CH0, 0, CMD_CALC },
{ FLD_PDC, UNIT_W, CH0, CALC_PDC_CH0, 0, CMD_CALC },
{ FLD_EFF, UNIT_PCT, CH0, CALC_EFF_CH0, 0, CMD_CALC }
{ FLD_YD, UNIT_WH, CH0, CALC_YD_CH0, 0, CMD_CALC },
{ FLD_YT, UNIT_KWH, CH0, CALC_YT_CH0, 0, CMD_CALC },
{ FLD_PDC, UNIT_W, CH0, CALC_PDC_CH0, 0, CMD_CALC },
{ FLD_EFF, UNIT_PCT, CH0, CALC_EFF_CH0, 0, CMD_CALC },
{ FLD_MP, UNIT_W, CH0, CALC_MPAC_CH0, 0, CMD_CALC }
};
#define HMS1CH_LIST_LEN (sizeof(hms1chAssignment) / sizeof(byteAssign_t))
#define HMS1CH_PAYLOAD_LEN 30
@ -40,32 +42,35 @@ const byteAssign_t hms1chAssignment[] = {
// HMS-800, HMS-1000
//-------------------------------------
const byteAssign_t hms2chAssignment[] = {
{ FLD_UDC, UNIT_V, CH1, 2, 2, 10 },
{ FLD_IDC, UNIT_A, CH1, 6, 2, 100 },
{ FLD_PDC, UNIT_W, CH1, 10, 2, 10 },
{ FLD_YT, UNIT_KWH, CH1, 14, 4, 1000 },
{ FLD_YD, UNIT_WH, CH1, 22, 2, 1 },
{ FLD_IRR, UNIT_PCT, CH1, CALC_IRR_CH, CH1, CMD_CALC },
{ FLD_UDC, UNIT_V, CH2, 4, 2, 10 },
{ FLD_IDC, UNIT_A, CH2, 8, 2, 100 },
{ FLD_PDC, UNIT_W, CH2, 12, 2, 10 },
{ FLD_YT, UNIT_KWH, CH2, 18, 4, 1000 },
{ FLD_YD, UNIT_WH, CH2, 24, 2, 1 },
{ FLD_IRR, UNIT_PCT, CH2, CALC_IRR_CH, CH2, CMD_CALC },
{ FLD_UAC, UNIT_V, CH0, 26, 2, 10 },
{ FLD_F, UNIT_HZ, CH0, 28, 2, 100 },
{ FLD_PAC, UNIT_W, CH0, 30, 2, 10 },
{ FLD_Q, UNIT_VAR, CH0, 32, 2, 10 }, // signed!
{ FLD_IAC, UNIT_A, CH0, 34, 2, 100 },
{ FLD_PF, UNIT_NONE, CH0, 36, 2, 1000 }, // signed!
{ FLD_T, UNIT_C, CH0, 38, 2, 10 }, // signed!
{ FLD_EVT, UNIT_NONE, CH0, 40, 2, 1 },
{ FLD_YD, UNIT_WH, CH0, CALC_YD_CH0, 0, CMD_CALC },
{ FLD_YT, UNIT_KWH, CH0, CALC_YT_CH0, 0, CMD_CALC },
{ FLD_PDC, UNIT_W, CH0, CALC_PDC_CH0, 0, CMD_CALC },
{ FLD_EFF, UNIT_PCT, CH0, CALC_EFF_CH0, 0, CMD_CALC }
{ FLD_UDC, UNIT_V, CH1, 2, 2, 10 },
{ FLD_IDC, UNIT_A, CH1, 6, 2, 100 },
{ FLD_PDC, UNIT_W, CH1, 10, 2, 10 },
{ FLD_YT, UNIT_KWH, CH1, 14, 4, 1000 },
{ FLD_YD, UNIT_WH, CH1, 22, 2, 1 },
{ FLD_IRR, UNIT_PCT, CH1, CALC_IRR_CH, CH1, CMD_CALC },
{ FLD_MP, UNIT_W, CH1, CALC_MPDC_CH, CH1, CMD_CALC },
{ FLD_UDC, UNIT_V, CH2, 4, 2, 10 },
{ FLD_IDC, UNIT_A, CH2, 8, 2, 100 },
{ FLD_PDC, UNIT_W, CH2, 12, 2, 10 },
{ FLD_YT, UNIT_KWH, CH2, 18, 4, 1000 },
{ FLD_YD, UNIT_WH, CH2, 24, 2, 1 },
{ FLD_IRR, UNIT_PCT, CH2, CALC_IRR_CH, CH2, CMD_CALC },
{ FLD_MP, UNIT_W, CH2, CALC_MPDC_CH, CH2, CMD_CALC },
{ FLD_UAC, UNIT_V, CH0, 26, 2, 10 },
{ FLD_F, UNIT_HZ, CH0, 28, 2, 100 },
{ FLD_PAC, UNIT_W, CH0, 30, 2, 10 },
{ FLD_Q, UNIT_VAR, CH0, 32, 2, 10 }, // signed!
{ FLD_IAC, UNIT_A, CH0, 34, 2, 100 },
{ FLD_PF, UNIT_NONE, CH0, 36, 2, 1000 }, // signed!
{ FLD_T, UNIT_C, CH0, 38, 2, 10 }, // signed!
{ FLD_EVT, UNIT_NONE, CH0, 40, 2, 1 },
{ FLD_YD, UNIT_WH, CH0, CALC_YD_CH0, 0, CMD_CALC },
{ FLD_YT, UNIT_KWH, CH0, CALC_YT_CH0, 0, CMD_CALC },
{ FLD_PDC, UNIT_W, CH0, CALC_PDC_CH0, 0, CMD_CALC },
{ FLD_EFF, UNIT_PCT, CH0, CALC_EFF_CH0, 0, CMD_CALC },
{ FLD_MP, UNIT_W, CH0, CALC_MPAC_CH0, 0, CMD_CALC }
};
#define HMS2CH_LIST_LEN (sizeof(hms2chAssignment) / sizeof(byteAssign_t))
#define HMS2CH_PAYLOAD_LEN 42
@ -80,6 +85,7 @@ const byteAssign_t hms4chAssignment[] = {
{ FLD_YT, UNIT_KWH, CH1, 14, 4, 1000 },
{ FLD_YD, UNIT_WH, CH1, 22, 2, 1 },
{ FLD_IRR, UNIT_PCT, CH1, CALC_IRR_CH, CH1, CMD_CALC },
{ FLD_MP, UNIT_W, CH1, CALC_MPDC_CH, CH1, CMD_CALC },
{ FLD_UDC, UNIT_V, CH2, 4, 2, 10 },
{ FLD_IDC, UNIT_A, CH2, 8, 2, 100 },
@ -87,6 +93,7 @@ const byteAssign_t hms4chAssignment[] = {
{ FLD_YT, UNIT_KWH, CH2, 18, 4, 1000 },
{ FLD_YD, UNIT_WH, CH2, 24, 2, 1 },
{ FLD_IRR, UNIT_PCT, CH2, CALC_IRR_CH, CH2, CMD_CALC },
{ FLD_MP, UNIT_W, CH2, CALC_MPDC_CH, CH2, CMD_CALC },
{ FLD_UDC, UNIT_V, CH3, 26, 2, 10 },
{ FLD_IDC, UNIT_A, CH3, 30, 2, 100 },
@ -94,6 +101,7 @@ const byteAssign_t hms4chAssignment[] = {
{ FLD_YT, UNIT_KWH, CH3, 38, 4, 1000 },
{ FLD_YD, UNIT_WH, CH3, 46, 2, 1 },
{ FLD_IRR, UNIT_PCT, CH3, CALC_IRR_CH, CH3, CMD_CALC },
{ FLD_MP, UNIT_W, CH3, CALC_MPDC_CH, CH3, CMD_CALC },
{ FLD_UDC, UNIT_V, CH4, 28, 2, 10 },
{ FLD_IDC, UNIT_A, CH4, 32, 2, 100 },
@ -101,6 +109,7 @@ const byteAssign_t hms4chAssignment[] = {
{ FLD_YT, UNIT_KWH, CH4, 42, 4, 1000 },
{ FLD_YD, UNIT_WH, CH4, 48, 2, 1 },
{ FLD_IRR, UNIT_PCT, CH4, CALC_IRR_CH, CH4, CMD_CALC },
{ FLD_MP, UNIT_W, CH4, CALC_MPDC_CH, CH4, CMD_CALC },
{ FLD_UAC, UNIT_V, CH0, 50, 2, 10 },
{ FLD_F, UNIT_HZ, CH0, 52, 2, 100 },
@ -110,10 +119,11 @@ const byteAssign_t hms4chAssignment[] = {
{ FLD_PF, UNIT_NONE, CH0, 60, 2, 1000 }, // signed!
{ FLD_T, UNIT_C, CH0, 62, 2, 10 }, // signed!
{ FLD_EVT, UNIT_NONE, CH0, 64, 2, 1 },
{ FLD_YD, UNIT_WH, CH0, CALC_YD_CH0, 0, CMD_CALC },
{ FLD_YT, UNIT_KWH, CH0, CALC_YT_CH0, 0, CMD_CALC },
{ FLD_PDC, UNIT_W, CH0, CALC_PDC_CH0, 0, CMD_CALC },
{ FLD_EFF, UNIT_PCT, CH0, CALC_EFF_CH0, 0, CMD_CALC }
{ FLD_YD, UNIT_WH, CH0, CALC_YD_CH0, 0, CMD_CALC },
{ FLD_YT, UNIT_KWH, CH0, CALC_YT_CH0, 0, CMD_CALC },
{ FLD_PDC, UNIT_W, CH0, CALC_PDC_CH0, 0, CMD_CALC },
{ FLD_EFF, UNIT_PCT, CH0, CALC_EFF_CH0, 0, CMD_CALC },
{ FLD_MP, UNIT_W, CH0, CALC_MPAC_CH0, 0, CMD_CALC }
};
#define HMS4CH_LIST_LEN (sizeof(hms4chAssignment) / sizeof(byteAssign_t))
#define HMS4CH_PAYLOAD_LEN 66
@ -128,6 +138,7 @@ const byteAssign_t hmt6chAssignment[] = {
{ FLD_YT, UNIT_KWH, CH1, 12, 4, 1000 },
{ FLD_YD, UNIT_WH, CH1, 20, 2, 1 },
{ FLD_IRR, UNIT_PCT, CH1, CALC_IRR_CH, CH1, CMD_CALC },
{ FLD_MP, UNIT_W, CH1, CALC_MPDC_CH, CH1, CMD_CALC },
{ FLD_UDC, UNIT_V, CH2, CALC_UDC_CH, CH1, CMD_CALC },
{ FLD_IDC, UNIT_A, CH2, 6, 2, 100 },
@ -135,6 +146,7 @@ const byteAssign_t hmt6chAssignment[] = {
{ FLD_YT, UNIT_KWH, CH2, 16, 4, 1000 },
{ FLD_YD, UNIT_WH, CH2, 22, 2, 1 },
{ FLD_IRR, UNIT_PCT, CH2, CALC_IRR_CH, CH2, CMD_CALC },
{ FLD_MP, UNIT_W, CH2, CALC_MPDC_CH, CH2, CMD_CALC },
{ FLD_UDC, UNIT_V, CH3, 24, 2, 10 },
{ FLD_IDC, UNIT_A, CH3, 26, 2, 100 },
@ -142,6 +154,7 @@ const byteAssign_t hmt6chAssignment[] = {
{ FLD_YT, UNIT_KWH, CH3, 34, 4, 1000 },
{ FLD_YD, UNIT_WH, CH3, 42, 2, 1 },
{ FLD_IRR, UNIT_PCT, CH3, CALC_IRR_CH, CH3, CMD_CALC },
{ FLD_MP, UNIT_W, CH3, CALC_MPDC_CH, CH3, CMD_CALC },
{ FLD_UDC, UNIT_V, CH4, CALC_UDC_CH, CH3, CMD_CALC },
{ FLD_IDC, UNIT_A, CH4, 28, 2, 100 },
@ -149,6 +162,7 @@ const byteAssign_t hmt6chAssignment[] = {
{ FLD_YT, UNIT_KWH, CH4, 38, 4, 1000 },
{ FLD_YD, UNIT_WH, CH4, 44, 2, 1 },
{ FLD_IRR, UNIT_PCT, CH4, CALC_IRR_CH, CH4, CMD_CALC },
{ FLD_MP, UNIT_W, CH4, CALC_MPDC_CH, CH4, CMD_CALC },
{ FLD_UDC, UNIT_V, CH5, 46, 2, 10 },
{ FLD_IDC, UNIT_A, CH5, 48, 2, 100 },
@ -156,6 +170,7 @@ const byteAssign_t hmt6chAssignment[] = {
{ FLD_YT, UNIT_KWH, CH5, 56, 4, 1000 },
{ FLD_YD, UNIT_WH, CH5, 64, 2, 1 },
{ FLD_IRR, UNIT_PCT, CH5, CALC_IRR_CH, CH5, CMD_CALC },
{ FLD_MP, UNIT_W, CH5, CALC_MPDC_CH, CH5, CMD_CALC },
{ FLD_UDC, UNIT_V, CH6, CALC_UDC_CH, CH5, CMD_CALC },
{ FLD_IDC, UNIT_A, CH6, 50, 2, 100 },
@ -163,6 +178,7 @@ const byteAssign_t hmt6chAssignment[] = {
{ FLD_YT, UNIT_KWH, CH6, 60, 4, 1000 },
{ FLD_YD, UNIT_WH, CH6, 66, 2, 1 },
{ FLD_IRR, UNIT_PCT, CH6, CALC_IRR_CH, CH6, CMD_CALC },
{ FLD_MP, UNIT_W, CH6, CALC_MPDC_CH, CH6, CMD_CALC },
{ FLD_UAC_1N, UNIT_V, CH0, 68, 2, 10 },
{ FLD_UAC_2N, UNIT_V, CH0, 70, 2, 10 },
@ -179,10 +195,11 @@ const byteAssign_t hmt6chAssignment[] = {
{ FLD_PF, UNIT_NONE, CH0, 92, 2, 1000 },
{ FLD_T, UNIT_C, CH0, 94, 2, 10 },
{ FLD_EVT, UNIT_NONE, CH0, 96, 2, 1 },
{ FLD_YD, UNIT_WH, CH0, CALC_YD_CH0, 0, CMD_CALC },
{ FLD_YT, UNIT_KWH, CH0, CALC_YT_CH0, 0, CMD_CALC },
{ FLD_PDC, UNIT_W, CH0, CALC_PDC_CH0, 0, CMD_CALC },
{ FLD_EFF, UNIT_PCT, CH0, CALC_EFF_CH0, 0, CMD_CALC }
{ FLD_YD, UNIT_WH, CH0, CALC_YD_CH0, 0, CMD_CALC },
{ FLD_YT, UNIT_KWH, CH0, CALC_YT_CH0, 0, CMD_CALC },
{ FLD_PDC, UNIT_W, CH0, CALC_PDC_CH0, 0, CMD_CALC },
{ FLD_EFF, UNIT_PCT, CH0, CALC_EFF_CH0, 0, CMD_CALC },
{ FLD_MP, UNIT_W, CH0, CALC_MPAC_CH0, 0, CMD_CALC }
};
#define HMT6CH_LIST_LEN (sizeof(hmt6chAssignment) / sizeof(byteAssign_t))
#define HMT6CH_PAYLOAD_LEN 98

4
src/hms/hmsRadio.h

@ -98,10 +98,10 @@ class CmtRadio {
initPacket(ivId, reqfld, ALL_FRAMES);
mTxBuf[10] = cmd;
CP_U32_LittleEndian(&mTxBuf[12], ts);
/*if (cmd == RealTimeRunData_Debug || cmd == AlarmData ) {
if (cmd == AlarmData ) { //cmd == RealTimeRunData_Debug ||
mTxBuf[18] = (alarmMesId >> 8) & 0xff;
mTxBuf[19] = (alarmMesId ) & 0xff;
}*/
}
sendPacket(24, isRetransmit);
}

20
src/publisher/pubMqtt.h

@ -24,8 +24,6 @@
#include "pubMqttDefs.h"
#include "pubMqttIvData.h"
#define QOS_0 0
typedef std::function<void(JsonObject)> subscriptionCb;
typedef struct {
@ -60,8 +58,8 @@ class PubMqtt {
mIntervalTimeout = 1;
mSendIvData.setup(sys, utcTs, &mSendList);
mSendIvData.setPublishFunc([this](const char *subTopic, const char *payload, bool retained) {
publish(subTopic, payload, retained);
mSendIvData.setPublishFunc([this](const char *subTopic, const char *payload, bool retained, uint8_t qos) {
publish(subTopic, payload, retained, true, qos);
});
mDiscovery.running = false;
@ -177,7 +175,7 @@ class PubMqtt {
mSendAlarm[iv->id] = true;
}
void publish(const char *subTopic, const char *payload, bool retained = false, bool addTopic = true) {
void publish(const char *subTopic, const char *payload, bool retained = false, bool addTopic = true, uint8_t qos = QOS_0) {
if(!mClient.connected())
return;
@ -186,15 +184,15 @@ class PubMqtt {
else
snprintf(mTopic, MQTT_TOPIC_LEN + 32 + MAX_NAME_LENGTH + 1, "%s", subTopic);
mClient.publish(mTopic, QOS_0, retained, payload);
mClient.publish(mTopic, qos, retained, payload);
yield();
mTxCnt++;
}
void subscribe(const char *subTopic) {
void subscribe(const char *subTopic, uint8_t qos = QOS_0) {
char topic[MQTT_TOPIC_LEN + 20];
snprintf(topic, (MQTT_TOPIC_LEN + 20), "%s/%s", mCfgMqtt->topic, subTopic);
mClient.subscribe(topic, QOS_0);
mClient.subscribe(topic, qos);
}
void setSubscriptionCb(subscriptionCb cb) {
@ -224,7 +222,7 @@ class PubMqtt {
void setPowerLimitAck(Inverter<> *iv) {
if (NULL != iv) {
snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "%s/%s", iv->config->name, subtopics[MQTT_ACK_PWR_LMT]);
publish(mSubTopic, "true", true);
publish(mSubTopic, "true", true, true, QOS_2);
}
}
@ -244,7 +242,7 @@ class PubMqtt {
for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) {
snprintf(mVal, 20, "ctrl/limit/%d", i);
subscribe(mVal);
subscribe(mVal, QOS_2);
snprintf(mVal, 20, "ctrl/restart/%d", i);
subscribe(mVal);
snprintf(mVal, 20, "ctrl/power/%d", i);
@ -525,7 +523,7 @@ class PubMqtt {
publish(mSubTopic, mVal, true);
snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "%s/alarm/%d/str", iv->config->name, j);
snprintf(mVal, 40, "%s", iv->getAlarmStr(iv->lastAlarm[j].code));
snprintf(mVal, 40, "%s", iv->getAlarmStr(iv->lastAlarm[j].code).c_str());
publish(mSubTopic, mVal, true);
snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "%s/alarm/%d/start", iv->config->name, j);

2
src/publisher/pubMqttDefs.h

@ -8,6 +8,8 @@
#include <Arduino.h>
enum { QOS_0 = 0, QOS_1, QOS_2 };
enum {
STR_TRUE,
STR_FALSE

12
src/publisher/pubMqttIvData.h

@ -10,7 +10,7 @@
#include "../hm/hmSystem.h"
#include "pubMqttDefs.h"
typedef std::function<void(const char *subTopic, const char *payload, bool retained)> pubMqttPublisherType;
typedef std::function<void(const char *subTopic, const char *payload, bool retained, uint8_t qos)> pubMqttPublisherType;
struct sendListCmdIv {
uint8_t cmd;
@ -104,7 +104,7 @@ class PubMqttIvData {
record_t<> *rec = mIv->getRecordStruct(mCmd);
snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "%s/last_success", mIv->config->name);
snprintf(mVal, 40, "%d", mIv->getLastTs(rec));
mPublish(mSubTopic, mVal, true);
mPublish(mSubTopic, mVal, true, QOS_0);
mIv->isProducing(); // recalculate status
mState = SEND_DATA;
@ -160,10 +160,14 @@ class PubMqttIvData {
} else
mIvLastRTRpub[mIv->id] = lastTs;
uint8_t qos = QOS_0;
if(FLD_ACT_ACTIVE_PWR_LIMIT == rec->assign[mPos].fieldId)
qos = QOS_2;
if((mIvSend == mIv) || (NULL == mIvSend)) { // send only updated values, or all if the inverter is NULL
snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "%s/ch%d/%s", mIv->config->name, rec->assign[mPos].ch, fields[rec->assign[mPos].fieldId]);
snprintf(mVal, 40, "%g", ah::round3(mIv->getValue(mPos, rec)));
mPublish(mSubTopic, mVal, retained);
mPublish(mSubTopic, mVal, retained, qos);
}
mPos++;
} else
@ -204,7 +208,7 @@ class PubMqttIvData {
}
snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "total/%s", fields[fieldId]);
snprintf(mVal, 40, "%g", ah::round3(mTotal[mPos]));
mPublish(mSubTopic, mVal, retained);
mPublish(mSubTopic, mVal, retained, QOS_0);
mPos++;
} else {
mSendList->pop();

12
src/web/RestApi.h

@ -27,9 +27,9 @@
#define F(sl) (sl)
#endif
const uint8_t acList[] = {FLD_UAC, FLD_IAC, FLD_PAC, FLD_F, FLD_PF, FLD_T, FLD_YT, FLD_YD, FLD_PDC, FLD_EFF, FLD_Q};
const uint8_t acListHmt[] = {FLD_UAC_1N, FLD_IAC_1, FLD_PAC, FLD_F, FLD_PF, FLD_T, FLD_YT, FLD_YD, FLD_PDC, FLD_EFF, FLD_Q};
const uint8_t dcList[] = {FLD_UDC, FLD_IDC, FLD_PDC, FLD_YD, FLD_YT, FLD_IRR};
const uint8_t acList[] = {FLD_UAC, FLD_IAC, FLD_PAC, FLD_F, FLD_PF, FLD_T, FLD_YT, FLD_YD, FLD_PDC, FLD_EFF, FLD_Q, FLD_MP};
const uint8_t acListHmt[] = {FLD_UAC_1N, FLD_IAC_1, FLD_PAC, FLD_F, FLD_PF, FLD_T, FLD_YT, FLD_YD, FLD_PDC, FLD_EFF, FLD_Q, FLD_MP};
const uint8_t dcList[] = {FLD_UDC, FLD_IDC, FLD_PDC, FLD_YD, FLD_YT, FLD_IRR, FLD_MP};
template<class HMSYSTEM, class HMRADIO>
class RestApi {
@ -365,6 +365,7 @@ class RestApi {
obj[F("power_limit_ack")] = iv->powerLimitAck;
obj[F("ts_last_success")] = rec->ts;
obj[F("generation")] = iv->ivGen;
obj[F("status")] = (uint8_t)iv->status;
JsonArray ch = obj.createNestedArray("ch");
@ -403,7 +404,10 @@ class RestApi {
return;
}
obj["cnt"] = iv->alarmCnt;
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug);
obj["cnt"] = iv->alarmCnt;
obj["last_id"] = iv->getChannelFieldValue(CH0, FLD_EVT, rec);
JsonArray alarm = obj.createNestedArray(F("alarm"));
for(uint8_t i = 0; i < 10; i++) {

2
src/web/html/colorBright.css

@ -20,6 +20,8 @@
--total-bg: #b06e04;
--iv-head-title: #1c6800;
--iv-head-bg: #32b004;
--iv-dis-title: #888;
--iv-dis: #999;
--ch-head-title: #003c80;
--ch-head-bg: #006ec0;
--ts-head: #333;

2
src/web/html/colorDark.css

@ -20,6 +20,8 @@
--total-bg: #666622;
--iv-head-title: #115511;
--iv-head-bg: #226622;
--iv-dis-title: #333;
--iv-dis: #444;
--ch-head-title: #112255;
--ch-head-bg: #223366;
--ts-head: #333;

1
src/web/html/index.html

@ -217,6 +217,7 @@
function parseRelease(obj) {
release = obj["name"].substring(6);
getAjax("/api/index", parse);
}
getAjax("/api/index", parse);

10
src/web/html/style.css

@ -141,6 +141,16 @@ span.seperator {
color: var(--fg2);
}
.iv-h-dis {
background-color: var(--iv-dis-title);
color: var(--fg2);
}
.iv-bg-dis {
background-color: var(--iv-dis);
color: var(--fg2);
}
.ch-h {
background-color: var(--ch-head-title);
color: var(--fg2);

30
src/web/html/visualization.html

@ -87,22 +87,26 @@
);
}
function ivHead(obj) {
total[0] += obj.ch[0][2]; // P_AC
total[1] += obj.ch[0][7]; // YieldDay
total[2] += obj.ch[0][6]; // YieldTotal
total[3] += obj.ch[0][8]; // P_DC
total[4] += obj.ch[0][10]; // Q_AC
if(0 != obj.status) { // only add totals if inverter is online
total[0] += obj.ch[0][2]; // P_AC
total[1] += obj.ch[0][7]; // YieldDay
total[2] += obj.ch[0][6]; // YieldTotal
total[3] += obj.ch[0][8]; // P_DC
total[4] += obj.ch[0][10]; // Q_AC
}
var t = span("&nbsp;&deg;C");
var clh = (0 == obj.status) ? "iv-h-dis" : "iv-h";
var clbg = (0 == obj.status) ? "iv-bg-dis" : "iv-bg";
return ml("div", {class: "row mt-2"},
ml("div", {class: "col"}, [
ml("div", {class: "p-2 iv-h"},
ml("div", {class: "p-2 " + clh},
ml("div", {class: "row"}, [
ml("div", {class: "col mx-2 mx-md-1"}, obj.name),
ml("div", {class: "col a-c"}, "Power limit " + ((obj.power_limit_read == 65535) ? "n/a" : (obj.power_limit_read + "&nbsp;%"))),
ml("div", {class: "col a-r mx-2 mx-md-1"}, String(obj.ch[0][5]) + t.innerText)
])
),
ml("div", {class: "p-2 iv-bg"}, [
ml("div", {class: "p-2 " + clbg}, [
ml("div", {class: "row"},[
numBig(obj.ch[0][2], "W", "AC Power"),
numBig(obj.ch[0][7], "Wh", "Yield Day"),
@ -110,6 +114,7 @@
]),
ml("div", {class: "hr"}),
ml("div", {class: "row mt-2"},[
numMid(obj.ch[0][11], "W", "Max AC Power"),
numMid(obj.ch[0][8], "W", "DC Power"),
numMid(obj.ch[0][0], "V", "Voltage"),
numMid(obj.ch[0][1], "A", "Current"),
@ -138,12 +143,15 @@
]);
}
function ch(name, vals) {
function ch(status, name, vals) {
var clh = (0 == status) ? "iv-h-dis" : "iv-h";
var clbg = (0 == status) ? "iv-bg-dis" : "iv-bg";
return ml("div", {class: "col-6 col-md-3 mt-2"}, [
ml("div", {class: "ch-h p-2 a-c"}, name),
ml("div", {class: "p-2 ch-bg"}, [
ml("div", {class: "p-2 a-c " + clh}, name),
ml("div", {class: "p-2 " + clbg}, [
ml("div", {class: "row"}, [
numCh(vals[2], units[2], "Power"),
numCh(vals[6], units[2], "Max Power"),
numCh(vals[5], units[5], "Irradiation"),
numCh(vals[3], units[3], "Yield Day"),
numCh(vals[4], units[4], "Yield Total"),
@ -182,7 +190,7 @@
if(name.length == 0)
name = "CHANNEL " + i;
if(obj.ch_max_pwr[i] > 0) // show channel only if max mod pwr
chn.push(ch(name, obj.ch[i]));
chn.push(ch(obj.status, name, obj.ch[i]));
}
mIvHtml.push(
ml("div", {}, [

Loading…
Cancel
Save