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}");