diff --git a/tools/esp8266/app.cpp b/tools/esp8266/app.cpp index 75fe77df..1d088840 100644 --- a/tools/esp8266/app.cpp +++ b/tools/esp8266/app.cpp @@ -239,6 +239,10 @@ void app::loop(void) { if(!mPayload[iv->id].complete) { mRxFailed++; + iv->setQueuedCmdFinished(); // command failed + if(mConfig.serialDebug) { + DPRINTLN(DBG_INFO, F("enqueued cmd failed/timeout")); + } if(mConfig.serialDebug) { DPRINT(DBG_INFO, F("Inverter #") + String(iv->id) + " "); DPRINTLN(DBG_INFO, F("no Payload received! (retransmits: ") + String(mPayload[iv->id].retransmits) + ")"); @@ -551,18 +555,12 @@ String app::getLiveData(void) modHtml += F("
" "
") + - String(iv->name) + F(" Limit ") + String(iv->actPowerLimit); - if (true) - { // live Power Limit from inverter is always in % - modHtml += F(" %"); - } - else - { - modHtml += F(" W"); - } + String(iv->name) + F(" Limit ") + String(iv->actPowerLimit) + + F("% | last Alarm: ") + iv->lastAlarmMsg + F(""); + uint8_t list[] = {FLD_UAC, FLD_IAC, FLD_PAC, FLD_F, FLD_PCT, FLD_T, FLD_YT, FLD_YD, FLD_PDC, FLD_EFF, FLD_PRA, FLD_ALARM_MES_ID}; - for (uint8_t fld = 0; fld < 12; fld++) + for (uint8_t fld = 0; fld < 11; fld++) { pos = (iv->getPosByChFld(CH0, list[fld])); if (0xff != pos) diff --git a/tools/esp8266/defines.h b/tools/esp8266/defines.h index 4d55a7fc..ef0ea40a 100644 --- a/tools/esp8266/defines.h +++ b/tools/esp8266/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 5 -#define VERSION_PATCH 15 +#define VERSION_PATCH 16 //------------------------------------- diff --git a/tools/esp8266/hmDefines.h b/tools/esp8266/hmDefines.h index 36139bb2..6330db98 100644 --- a/tools/esp8266/hmDefines.h +++ b/tools/esp8266/hmDefines.h @@ -23,9 +23,13 @@ const char* const units[] = {"V", "A", "W", "Wh", "kWh", "Hz", "°C", "%","VAr", // field types enum {FLD_UDC = 0, FLD_IDC, FLD_PDC, FLD_YD, FLD_YW, FLD_YT, - FLD_UAC, FLD_IAC, FLD_PAC, FLD_F, FLD_T, FLD_PCT, FLD_EFF, FLD_IRR, FLD_PRA,FLD_ALARM_MES_ID,FLD_FW_VERSION,FLD_FW_BUILD_YEAR,FLD_FW_BUILD_MONTH_DAY,FLD_HW_ID,FLD_ACT_PWR_LIMIT}; + FLD_UAC, FLD_IAC, FLD_PAC, FLD_F, FLD_T, FLD_PCT, FLD_EFF, + FLD_IRR, FLD_PRA,FLD_ALARM_MES_ID,FLD_FW_VERSION,FLD_FW_BUILD_YEAR, + FLD_FW_BUILD_MONTH_DAY,FLD_HW_ID,FLD_ACT_PWR_LIMIT,FLD_LAST_ALARM_CODE}; + const char* const fields[] = {"U_DC", "I_DC", "P_DC", "YieldDay", "YieldWeek", "YieldTotal", - "U_AC", "I_AC", "P_AC", "Freq", "Temp", "Pct", "Efficiency", "Irradiation","P_ACr","ALARM_MES_ID","FWVersion","FWBuildYear","FWBuildMonthDay","HWPartId","PowerLimit"}; + "U_AC", "I_AC", "P_AC", "Freq", "Temp", "Pct", "Efficiency", "Irradiation","P_ACr", + "ALARM_MES_ID","FWVersion","FWBuildYear","FWBuildMonthDay","HWPartId","PowerLimit","LastAlarmCode"}; // 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}; @@ -97,6 +101,10 @@ const byteAssign_t SystemConfigParaAssignment[] = { }; #define HMSYSTEM_LIST_LEN (sizeof(SystemConfigParaAssignment) / sizeof(byteAssign_t)) +const byteAssign_t AlarmDataAssignment[] = { + { FLD_LAST_ALARM_CODE, UNIT_NONE, CH0, 0, 2, 1 } +}; +#define HMALARMDATA_LIST_LEN (sizeof(AlarmDataAssignment) / sizeof(byteAssign_t)) diff --git a/tools/esp8266/hmInverter.h b/tools/esp8266/hmInverter.h index 774fd809..f1250ffd 100644 --- a/tools/esp8266/hmInverter.h +++ b/tools/esp8266/hmInverter.h @@ -115,6 +115,7 @@ class Inverter { RECORDTYPE *record; // pointer for values uint16_t chMaxPwr[4]; // maximum power of the modules (Wp) char chName[4][MAX_NAME_LENGTH]; // human readable name for channel + String lastAlarmMsg; bool initialized; // needed to check if the inverter was correctly added (ESP32 specific - union types are never null) Inverter() { @@ -126,6 +127,8 @@ class Inverter { devControlCmd = 0xff; initialized = false; fwVersion = 0; + lastAlarmMsg = "nothing"; + alarmMesIndex = 0; } ~Inverter() { @@ -164,8 +167,8 @@ class Inverter { memset(name, 0, MAX_NAME_LENGTH); memset(chName, 0, MAX_NAME_LENGTH * 4); memset(record, 0, sizeof(RECORDTYPE) * listLen); - enqueCommand(InverterDevInform_All); enqueCommand(SystemConfigPara); + enqueCommand(InverterDevInform_All); initialized = true; } @@ -206,12 +209,25 @@ class Inverter { val <<= 8; val |= buf[ptr]; } while(++ptr != end); - record[pos] = (RECORDTYPE)(val) / (RECORDTYPE)(div); + if ((RECORDTYPE)(div) > 1){ + record[pos] = (RECORDTYPE)(val) / (RECORDTYPE)(div); + } + else { + record[pos] = (RECORDTYPE)(val); + } + } if (cmd == RealTimeRunData_Debug) { // get last alarm message index and save it in the inverter object if (getPosByChFld(0, FLD_ALARM_MES_ID) == pos){ - alarmMesIndex = record[pos]; + if (alarmMesIndex < record[pos]){ + alarmMesIndex = record[pos]; + enqueCommand(AlarmUpdate); + enqueCommand(AlarmData); + } + else { + alarmMesIndex = record[pos]; // no change + } } } if (cmd == InverterDevInform_All) { @@ -228,6 +244,11 @@ class Inverter { DPRINT(DBG_DEBUG, F("Inverter actual power limit: ") + String(actPowerLimit)); } } + if (cmd == AlarmData){ + if (getPosByChFld(0, FLD_LAST_ALARM_CODE) == pos){ + lastAlarmMsg = getAlarmStr(record[pos]); + } + } } RECORDTYPE getValue(uint8_t pos) { @@ -307,10 +328,227 @@ class Inverter { listLen = (uint8_t)(HMSYSTEM_LIST_LEN); assign = (byteAssign_t *)SystemConfigParaAssignment; break; + case AlarmData: + listLen = (uint8_t)(HMALARMDATA_LIST_LEN); + assign = (byteAssign_t *)AlarmDataAssignment; + break; default: DPRINTLN(DBG_INFO, "Parser not implemented"); } } + String getAlarmStr(u_int16_t alarmCode) + { + switch (alarmCode) + { + case 1: + return String(F("Inverter start")); + break; + case 2: + return String(F("DTU command failed")); + break; + case 121: + return String(F("Over temperature protection")); + break; + case 125: + return String(F("Grid configuration parameter error")); + break; + case 126: + return String(F("Software error code 126")); + break; + case 127: + return String(F("Firmware error")); + break; + case 128: + return String(F("Software error code 128")); + break; + case 129: + return String(F("Software error code 129")); + break; + case 130: + return String(F("Offline")); + break; + case 141: + return String(F("Grid overvoltage")); + break; + case 142: + return String(F("Average grid overvoltage")); + break; + case 143: + return String(F("Grid undervoltage")); + break; + case 144: + return String(F("Grid overfrequency")); + break; + case 145: + return String(F("Grid underfrequency")); + break; + case 146: + return String(F("Rapid grid frequency change")); + break; + case 147: + return String(F("Power grid outage")); + break; + case 148: + return String(F("Grid disconnection")); + break; + case 149: + return String(F("Island detected")); + break; + case 205: + return String(F("Input port 1 & 2 overvoltage")); + break; + case 206: + return String(F("Input port 3 & 4 overvoltage")); + break; + case 207: + return String(F("Input port 1 & 2 undervoltage")); + break; + case 208: + return String(F("Input port 3 & 4 undervoltage")); + break; + case 209: + return String(F("Port 1 no input")); + break; + case 210: + return String(F("Port 2 no input")); + break; + case 211: + return String(F("Port 3 no input")); + break; + case 212: + return String(F("Port 4 no input")); + break; + case 213: + return String(F("PV-1 & PV-2 abnormal wiring")); + break; + case 214: + return String(F("PV-3 & PV-4 abnormal wiring")); + break; + case 215: + return String(F("PV-1 Input overvoltage")); + break; + case 216: + return String(F("PV-1 Input undervoltage")); + break; + case 217: + return String(F("PV-2 Input overvoltage")); + break; + case 218: + return String(F("PV-2 Input undervoltage")); + break; + case 219: + return String(F("PV-3 Input overvoltage")); + break; + case 220: + return String(F("PV-3 Input undervoltage")); + break; + case 221: + return String(F("PV-4 Input overvoltage")); + break; + case 222: + return String(F("PV-4 Input undervoltage")); + break; + case 301: + return String(F("Hardware error code 301")); + break; + case 302: + return String(F("Hardware error code 302")); + break; + case 303: + return String(F("Hardware error code 303")); + break; + case 304: + return String(F("Hardware error code 304")); + break; + case 305: + return String(F("Hardware error code 305")); + break; + case 306: + return String(F("Hardware error code 306")); + break; + case 307: + return String(F("Hardware error code 307")); + break; + case 308: + return String(F("Hardware error code 308")); + break; + case 309: + return String(F("Hardware error code 309")); + break; + case 310: + return String(F("Hardware error code 310")); + break; + case 311: + return String(F("Hardware error code 311")); + break; + case 312: + return String(F("Hardware error code 312")); + break; + case 313: + return String(F("Hardware error code 313")); + break; + case 314: + return String(F("Hardware error code 314")); + break; + case 5041: + return String(F("Error code-04 Port 1")); + break; + case 5042: + return String(F("Error code-04 Port 2")); + break; + case 5043: + return String(F("Error code-04 Port 3")); + break; + case 5044: + return String(F("Error code-04 Port 4")); + break; + case 5051: + return String(F("PV Input 1 Overvoltage/Undervoltage")); + break; + case 5052: + return String(F("PV Input 2 Overvoltage/Undervoltage")); + break; + case 5053: + return String(F("PV Input 3 Overvoltage/Undervoltage")); + break; + case 5054: + return String(F("PV Input 4 Overvoltage/Undervoltage")); + break; + case 5060: + return String(F("Abnormal bias")); + break; + case 5070: + return String(F("Over temperature protection")); + break; + case 5080: + return String(F("Grid Overvoltage/Undervoltage")); + break; + case 5090: + return String(F("Grid Overfrequency/Underfrequency")); + break; + case 5100: + return String(F("Island detected")); + break; + case 5120: + return String(F("EEPROM reading and writing error")); + break; + case 5150: + return String(F("10 min value grid overvoltage")); + break; + case 5200: + return String(F("Firmware error")); + break; + case 8310: + return String(F("Shut down")); + break; + case 9000: + return String(F("Microinverter is suspected of being stolen")); + break; + default: + return String(F("Unknown")); + break; + } + } private: std::queue> _commandQueue; diff --git a/tools/esp8266/web.cpp b/tools/esp8266/web.cpp index 72d680df..426a9803 100644 --- a/tools/esp8266/web.cpp +++ b/tools/esp8266/web.cpp @@ -488,6 +488,14 @@ void web::showWebApi(void) iv->devControlRequest = true; // queue it in the request loop } } + if (response["cmd"] == (uint8_t)TurnOff){ + iv->devControlCmd = TurnOff; + iv->devControlRequest = true; // queue it in the request loop + } + if (response["cmd"] == (uint8_t)TurnOn){ + iv->devControlCmd = TurnOn; + iv->devControlRequest = true; // queue it in the request loop + } } } mWeb->send(200, "text/json", "{success:true}");