|  |  | @ -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<InfoCommand>(InverterDevInform_All); | 
			
		
	
		
			
				
					|  |  |  |             enqueCommand<InfoCommand>(SystemConfigPara); | 
			
		
	
		
			
				
					|  |  |  |             enqueCommand<InfoCommand>(InverterDevInform_All); | 
			
		
	
		
			
				
					|  |  |  |             initialized = true; | 
			
		
	
		
			
				
					|  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  | @ -206,12 +209,25 @@ class Inverter { | 
			
		
	
		
			
				
					|  |  |  |                     val <<= 8; | 
			
		
	
		
			
				
					|  |  |  |                     val |= buf[ptr]; | 
			
		
	
		
			
				
					|  |  |  |                 } while(++ptr != end); | 
			
		
	
		
			
				
					|  |  |  |                 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){  | 
			
		
	
		
			
				
					|  |  |  |                     if (alarmMesIndex < record[pos]){ | 
			
		
	
		
			
				
					|  |  |  |                         alarmMesIndex = record[pos]; | 
			
		
	
		
			
				
					|  |  |  |                         enqueCommand<InfoCommand>(AlarmUpdate); | 
			
		
	
		
			
				
					|  |  |  |                         enqueCommand<InfoCommand>(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<std::shared_ptr<CommandAbstract>> _commandQueue; | 
			
		
	
	
		
			
				
					|  |  | 
 |