@ -4,13 +4,13 @@ 
			
		
	
		
			
				
					//-----------------------------------------------------------------------------
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					# if defined(ESP32) && defined(F)  
			
		
	
		
			
				
					   # undef F  
			
		
	
		
			
				
					   # define F(sl) (sl)  
			
		
	
		
			
				
					# undef F  
			
		
	
		
			
				
					# define F(sl) (sl)  
			
		
	
		
			
				
					# endif  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					# include  "app.h"  
			
		
	
		
			
				
					# include  <ArduinoJson.h>  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					# include  <ArduinoJson.h>  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					//-----------------------------------------------------------------------------
  
			
		
	
		
			
				
					app : : app ( )  {  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -27,20 +27,19 @@ app::app() { 
			
		
	
		
			
				
					    mShouldReboot  =  false ;  
			
		
	
		
			
				
					}  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					//-----------------------------------------------------------------------------
  
			
		
	
		
			
				
					void  app : : setup ( uint32_t  timeout )  {  
			
		
	
		
			
				
					    DPRINTLN ( DBG_VERBOSE ,  F ( " app::setup " ) ) ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    mWifiSettingsValid  =  checkEEpCrc ( ADDR_START ,  ADDR_WIFI_CRC ,  ADDR_WIFI_CRC ) ;  
			
		
	
		
			
				
					    mSettingsValid  =  checkEEpCrc ( ADDR_START_SETTINGS ,  ( ( ADDR_NEXT ) - ( ADDR_START_SETTINGS ) ) ,  ADDR_SETTINGS_CRC ) ;  
			
		
	
		
			
				
					    mSettingsValid  =  checkEEpCrc ( ADDR_START_SETTINGS ,  ( ( ADDR_NEXT )   -   ( ADDR_START_SETTINGS ) ) ,  ADDR_SETTINGS_CRC ) ;  
			
		
	
		
			
				
					    loadEEpconfig ( ) ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    mWifi - > setup ( timeout ,  mWifiSettingsValid ) ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					     # ifndef AP_ONLY  
			
		
	
		
			
				
					# ifndef AP_ONLY  
			
		
	
		
			
				
					    setupMqtt ( ) ;  
			
		
	
		
			
				
					     # endif  
			
		
	
		
			
				
					# endif  
			
		
	
		
			
				
					    mSys - > setup ( mConfig . amplifierPower ,  mConfig . pinIrq ,  mConfig . pinCe ,  mConfig . pinCs ) ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    mWebInst  =  new  web ( this ,  & mSysConfig ,  & mConfig ,  & mStat ,  mVersion ) ;  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -54,70 +53,71 @@ void app::loop(void) { 
			
		
	
		
			
				
					    bool  apActive  =  mWifi - > loop ( ) ;  
			
		
	
		
			
				
					    mWebInst - > loop ( ) ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    if ( millis ( )  -  mPrevMillis  > =  1000 )  {  
			
		
	
		
			
				
					    if   ( millis ( )  -  mPrevMillis  > =  1000 )  {  
			
		
	
		
			
				
					        mPrevMillis  + =  1000 ;  
			
		
	
		
			
				
					        mUptimeSecs + + ;  
			
		
	
		
			
				
					        if ( 0  ! =  mUtcTimestamp )  
			
		
	
		
			
				
					        if   ( 0  ! =  mUtcTimestamp )  
			
		
	
		
			
				
					            mUtcTimestamp + + ;  
			
		
	
		
			
				
					    }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    if ( checkTicker ( & mNtpRefreshTicker ,  mNtpRefreshInterval ) )  {  
			
		
	
		
			
				
					        if ( ! apActive )  
			
		
	
		
			
				
					    if   ( checkTicker ( & mNtpRefreshTicker ,  mNtpRefreshInterval ) )  {  
			
		
	
		
			
				
					        if   ( ! apActive )  
			
		
	
		
			
				
					            mUpdateNtp  =  true ;  
			
		
	
		
			
				
					    }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    if ( mUpdateNtp )  {  
			
		
	
		
			
				
					    if   ( mUpdateNtp )  {  
			
		
	
		
			
				
					        mUpdateNtp  =  false ;  
			
		
	
		
			
				
					        mUtcTimestamp  =  mWifi - > getNtpTime ( ) ;  
			
		
	
		
			
				
					        DPRINTLN ( DBG_INFO ,  F ( " [NTP]:  " )  +  getDateTimeStr ( mUtcTimestamp )  +  F ( "  UTC " ) ) ;  
			
		
	
		
			
				
					    }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    if ( mFlagSendDiscoveryConfig )  {  
			
		
	
		
			
				
					    if   ( mFlagSendDiscoveryConfig )  {  
			
		
	
		
			
				
					        mFlagSendDiscoveryConfig  =  false ;  
			
		
	
		
			
				
					        sendMqttDiscoveryConfig ( ) ;  
			
		
	
		
			
				
					    }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    if ( mShouldReboot )  {  
			
		
	
		
			
				
					    if   ( mShouldReboot )  {  
			
		
	
		
			
				
					        DPRINTLN ( DBG_INFO ,  F ( " Rebooting... " ) ) ;  
			
		
	
		
			
				
					        ESP . restart ( ) ;  
			
		
	
		
			
				
					    }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					     
			
		
	
		
			
				
					    mSys - > Radio . loop ( ) ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    yield ( ) ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    if ( checkTicker ( & mRxTicker ,  5 ) )  {  
			
		
	
		
			
				
					    if   ( checkTicker ( & mRxTicker ,  5 ) )  {  
			
		
	
		
			
				
					        bool  rxRdy  =  mSys - > Radio . switchRxCh ( ) ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					        if ( ! mSys - > BufCtrl . empty ( ) )  {  
			
		
	
		
			
				
					        if   ( ! mSys - > BufCtrl . empty ( ) )  {  
			
		
	
		
			
				
					            uint8_t  len ;  
			
		
	
		
			
				
					            packet_t  * p  =  mSys - > BufCtrl . getBack ( ) ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					            if ( mSys - > Radio . checkPaketCrc ( p - > packet ,  & len ,  p - > rxCh ) )  {  
			
		
	
		
			
				
					            if   ( mSys - > Radio . checkPaketCrc ( p - > packet ,  & len ,  p - > rxCh ) )  {  
			
		
	
		
			
				
					                // process buffer only on first occurrence
  
			
		
	
		
			
				
					                if ( mConfig . serialDebug )  {  
			
		
	
		
			
				
					                if   ( mConfig . serialDebug )  {  
			
		
	
		
			
				
					                    DPRINT ( DBG_INFO ,  " RX  "  +  String ( len )  +  " B Ch "  +  String ( p - > rxCh )  +  "  |  " ) ;  
			
		
	
		
			
				
					                    mSys - > Radio . dumpBuf ( NULL ,  p - > packet ,  len ) ;  
			
		
	
		
			
				
					                }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                mStat . frmCnt + + ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                if ( 0  ! =  len )  {  
			
		
	
		
			
				
					                if   ( 0  ! =  len )  {  
			
		
	
		
			
				
					                    Inverter < >  * iv  =  mSys - > findInverter ( & p - > packet [ 1 ] ) ;  
			
		
	
		
			
				
					                    if ( ( NULL  ! =  iv )  & &  ( p - > packet [ 0 ]  = =  ( TX_REQ_INFO  +  0x80 ) ) )  {  // response from get information command
  
			
		
	
		
			
				
					                    if  ( ( NULL  ! =  iv )  & &  ( p - > packet [ 0 ]  = =  ( TX_REQ_INFO  +  ALL_FRAMES ) ) )   // response from get information command
  
			
		
	
		
			
				
					                    {  
			
		
	
		
			
				
					                        mPayload [ iv - > id ] . txId  =  p - > packet [ 0 ] ;  
			
		
	
		
			
				
					                        DPRINTLN ( DBG_DEBUG ,  F ( " Response from info request received " ) ) ;  
			
		
	
		
			
				
					                        uint8_t  * pid  =  & p - > packet [ 9 ] ;  
			
		
	
		
			
				
					                        if  ( * pid  = =  0x00 )  
			
		
	
		
			
				
					                            DPRINT ( DBG_DEBUG ,  " fragment number zero received and ignored " ) ;  
			
		
	
		
			
				
					                        else  {  
			
		
	
		
			
				
					                        if  ( * pid  = =  0x00 )  {   
			
		
	
		
			
				
					                            DPRINT ( DBG_DEBUG ,  F ( " fragment number zero received and ignored " ) ) ;  
			
		
	
		
			
				
					                        }  else  {  
			
		
	
		
			
				
					                            DPRINTLN ( DBG_DEBUG ,  " PID: 0x "  +  String ( * pid ,  HEX ) ) ;  
			
		
	
		
			
				
					                            if  ( ( * pid  &  0x7F )  <  5 )  {  
			
		
	
		
			
				
					                                memcpy ( mPayload [ iv - > id ] . data [ ( * pid  &  0x7F )  -  1 ] ,  & p - > packet [ 10 ] ,  len  -  11 ) ;  
			
		
	
		
			
				
					                                mPayload [ iv - > id ] . len [ ( * pid  &  0x7F )  -  1 ]  =  len  -  11 ;  
			
		
	
		
			
				
					                            }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                            if  ( ( * pid  &  0x80 )  = =  0x80 )  {  
			
		
	
		
			
				
					                            if  ( ( * pid  &  ALL_FRAMES )  = =  ALL_FRAMES )  {  
			
		
	
		
			
				
					                                // Last packet
  
			
		
	
		
			
				
					                                if  ( ( * pid  &  0x7f )  >  mPayload [ iv - > id ] . maxPackId )  {  
			
		
	
		
			
				
					                                    mPayload [ iv - > id ] . maxPackId  =  ( * pid  &  0x7f ) ;  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -127,15 +127,16 @@ void app::loop(void) { 
			
		
	
		
			
				
					                            }  
			
		
	
		
			
				
					                        }  
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					                    if ( ( NULL  ! =  iv )  & &  ( p - > packet [ 0 ]  = =  ( TX_REQ_DEVCONTROL  +  0x80 ) ) )  { // response from dev control command
  
			
		
	
		
			
				
					                        mPayload [ iv - > id ] . txId  =  p - > packet [ 0 ] ;   
			
		
	
		
			
				
					                    if   ( ( NULL  ! =  iv )  & &  ( p - > packet [ 0 ]  = =  ( TX_REQ_DEVCONTROL  +  ALL_FRAMES ) ) )   // response from dev control command
  
			
		
	
		
			
				
					                    {  
			
		
	
		
			
				
					                        DPRINTLN ( DBG_DEBUG ,  F ( " Response from devcontrol request received " ) ) ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                        mPayload [ iv - > id ] . txId  =  p - > packet [ 0 ] ;  
			
		
	
		
			
				
					                        iv - > devControlRequest  =  false ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                        if  ( ( p - > packet [ 12 ]  = =  ActivePowerContr )  & &  ( p - > packet [ 13 ]  = =  0x00 ) )  {  
			
		
	
		
			
				
					                            if  ( p - > packet [ 10 ]  = =  0x00  & &  p - > packet [ 11 ]  = =  0x00 )  
			
		
	
		
			
				
					                                DPRINTLN ( DBG_INFO ,  F ( " Inverter  " )  +  String ( iv - > id )  +  F ( "  has accepted power limit set point  " )  +  String ( iv - > powerLimit [ 0 ] )  +  F ( "  with PowerLimitControl  " )   +  String ( iv - > powerLimit [ 1 ] ) ) ;  
			
		
	
		
			
				
					                            else  
			
		
	
		
			
				
					                                DPRINTLN ( DBG_INFO ,  F ( " Inverter  " )  +  String ( iv - > id )  +  F ( "  has NOT accepted power limit set point " )  +  String ( iv - > powerLimit [ 0 ] )  +  F ( "  with PowerLimitControl  " )   +  String ( iv - > powerLimit [ 1 ] ) ) ;  
			
		
	
		
			
				
					                            String  msg  =  ( p - > packet [ 10 ]  = =  0x00  & &  p - > packet [ 11 ]  = =  0x00 )  ?  " "  :  " NOT  " ;  
			
		
	
		
			
				
					                            DPRINTLN ( DBG_INFO ,  F ( " Inverter  " )  +  String ( iv - > id )  +  F ( "  has  " )  +  msg  +  F ( " accepted power limit set point  " )  +  String ( iv - > powerLimit [ 0 ] )  +  F ( "  with PowerLimitControl  " )  +  String ( iv - > powerLimit [ 1 ] ) ) ;  
			
		
	
		
			
				
					                        }  
			
		
	
		
			
				
					                        iv - > devControlCmd  =  Init ;  
			
		
	
		
			
				
					                    }  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -145,17 +146,16 @@ void app::loop(void) { 
			
		
	
		
			
				
					        }  
			
		
	
		
			
				
					        yield ( ) ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					        if ( rxRdy )  {  
			
		
	
		
			
				
					        if  ( rxRdy )  {  
			
		
	
		
			
				
					            processPayload ( true ) ;  
			
		
	
		
			
				
					        }  
			
		
	
		
			
				
					    }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    if ( mMqttActive )  
			
		
	
		
			
				
					    if   ( mMqttActive )  
			
		
	
		
			
				
					        mMqtt . loop ( ) ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    if ( checkTicker ( & mTicker ,  1000 ) )  {  
			
		
	
		
			
				
					        if ( mUtcTimestamp  >  946684800  & &  mConfig . sunLat  & &  mConfig . sunLon  & &  ( mUtcTimestamp  +  mCalculatedTimezoneOffset )  /  86400  ! =  ( mLatestSunTimestamp  +  mCalculatedTimezoneOffset )  /  86400 )  {  // update on reboot or midnight
  
			
		
	
		
			
				
					    if   ( checkTicker ( & mTicker ,  1000 ) )  {  
			
		
	
		
			
				
					        if   ( mUtcTimestamp  >  946684800  & &  mConfig . sunLat  & &  mConfig . sunLon  & &  ( mUtcTimestamp  +  mCalculatedTimezoneOffset )  /  86400  ! =  ( mLatestSunTimestamp  +  mCalculatedTimezoneOffset )  /  86400 )  {    // update on reboot or midnight
  
			
		
	
		
			
				
					            if  ( ! mLatestSunTimestamp )  {                                                                                                                                                            // first call: calculate time zone from longitude to refresh at local midnight
  
			
		
	
		
			
				
					                mCalculatedTimezoneOffset  =  ( int8_t ) ( ( mConfig . sunLon  > =  0  ?  mConfig . sunLon  +  7.5  :  mConfig . sunLon  -  7.5 )  /  15 )  *  3600 ;  
			
		
	
		
			
				
					            }  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -163,11 +163,11 @@ void app::loop(void) { 
			
		
	
		
			
				
					            mLatestSunTimestamp  =  mUtcTimestamp ;  
			
		
	
		
			
				
					        }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					        if ( ( + + mMqttTicker  > =  mMqttInterval )  & &  ( mMqttInterval  ! =  0xffff )  & &  mMqttActive )  {  
			
		
	
		
			
				
					        if   ( ( + + mMqttTicker  > =  mMqttInterval )  & &  ( mMqttInterval  ! =  0xffff )  & &  mMqttActive )  {  
			
		
	
		
			
				
					            mMqttTicker  =  0 ;  
			
		
	
		
			
				
					            mMqtt . isConnected ( true ) ;   // really needed? See comment from HorstG-57 #176
  
			
		
	
		
			
				
					            char  val [ 10 ] ;  
			
		
	
		
			
				
					            snprintf ( val ,  10 ,  " %ld " ,  millis ( ) / 1000 ) ;  
			
		
	
		
			
				
					            snprintf ( val ,  10 ,  " %ld " ,  millis ( )   /   1000 ) ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					            mMqtt . sendMsg ( " uptime " ,  val ) ;  
			
		
	
		
			
				
					
 
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -190,22 +190,22 @@ void app::loop(void) { 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					# ifdef __MQTT_TEST__  
			
		
	
		
			
				
					            // für einfacheren Test mit MQTT, den MQTT abschnitt in 10 Sekunden wieder ausführen
  
			
		
	
		
			
				
					            mMqttTicker  =  mMqttInterval  - 10 ;  
			
		
	
		
			
				
					            mMqttTicker  =  mMqttInterval  -   10 ;  
			
		
	
		
			
				
					# endif  
			
		
	
		
			
				
					        }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					        if ( mConfig . serialShowIv )  {  
			
		
	
		
			
				
					            if ( + + mSerialTicker  > =  mConfig . serialInterval )  {  
			
		
	
		
			
				
					        if   ( mConfig . serialShowIv )  {  
			
		
	
		
			
				
					            if   ( + + mSerialTicker  > =  mConfig . serialInterval )  {  
			
		
	
		
			
				
					                mSerialTicker  =  0 ;  
			
		
	
		
			
				
					                char  topic [ 30 ] ,  val [ 10 ] ;  
			
		
	
		
			
				
					                for ( uint8_t  id  =  0 ;  id  <  mSys - > getNumInverters ( ) ;  id + + )  {  
			
		
	
		
			
				
					                for   ( uint8_t  id  =  0 ;  id  <  mSys - > getNumInverters ( ) ;  id + + )  {  
			
		
	
		
			
				
					                    Inverter < >  * iv  =  mSys - > getInverterByPos ( id ) ;  
			
		
	
		
			
				
					                    if ( NULL  ! =  iv )  {  
			
		
	
		
			
				
					                    if   ( NULL  ! =  iv )  {  
			
		
	
		
			
				
					                        record_t < >  * rec  =  iv - > getRecordStruct ( RealTimeRunData_Debug ) ;  
			
		
	
		
			
				
					                        if ( iv - > isAvailable ( mUtcTimestamp ,  rec ) )  {  
			
		
	
		
			
				
					                        if   ( iv - > isAvailable ( mUtcTimestamp ,  rec ) )  {  
			
		
	
		
			
				
					                            DPRINTLN ( DBG_INFO ,  " Inverter:  "  +  String ( id ) ) ;  
			
		
	
		
			
				
					                            for ( uint8_t  i  =  0 ;  i  <  rec - > length ;  i + + )  {  
			
		
	
		
			
				
					                                if ( 0.0f  ! =  iv - > getValue ( i ,  rec ) )  {  
			
		
	
		
			
				
					                            for   ( uint8_t  i  =  0 ;  i  <  rec - > length ;  i + + )  {  
			
		
	
		
			
				
					                                if   ( 0.0f  ! =  iv - > getValue ( i ,  rec ) )  {  
			
		
	
		
			
				
					                                    snprintf ( topic ,  30 ,  " %s/ch%d/%s " ,  iv - > name ,  rec - > assign [ i ] . ch ,  iv - > getFieldName ( i ,  rec ) ) ;  
			
		
	
		
			
				
					                                    snprintf ( val ,  10 ,  " %.3f %s " ,  iv - > getValue ( i ,  rec ) ,  iv - > getUnit ( i ,  rec ) ) ;  
			
		
	
		
			
				
					                                    DPRINTLN ( DBG_INFO ,  String ( topic )  +  " :  "  +  String ( val ) ) ;  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -219,41 +219,41 @@ void app::loop(void) { 
			
		
	
		
			
				
					            }  
			
		
	
		
			
				
					        }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					        if ( + + mSendTicker  > =  mConfig . sendInterval )  {  
			
		
	
		
			
				
					        if   ( + + mSendTicker  > =  mConfig . sendInterval )  {  
			
		
	
		
			
				
					            mSendTicker  =  0 ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					            if ( mUtcTimestamp  >  946684800  & &  ( ! mConfig . sunDisNightCom  | |  ! mLatestSunTimestamp  | |  ( mUtcTimestamp  > =  mSunrise  & &  mUtcTimestamp  < =  mSunset ) ) )  {  // Timestamp is set and (inverter communication only during the day if the option is activated and sunrise/sunset is set)
  
			
		
	
		
			
				
					                if ( mConfig . serialDebug )  
			
		
	
		
			
				
					            if   ( mUtcTimestamp  >  946684800  & &  ( ! mConfig . sunDisNightCom  | |  ! mLatestSunTimestamp  | |  ( mUtcTimestamp  > =  mSunrise  & &  mUtcTimestamp  < =  mSunset ) ) )  {    // Timestamp is set and (inverter communication only during the day if the option is activated and sunrise/sunset is set)
  
			
		
	
		
			
				
					                if   ( mConfig . serialDebug )  
			
		
	
		
			
				
					                    DPRINTLN ( DBG_DEBUG ,  F ( " Free heap: 0x " )  +  String ( ESP . getFreeHeap ( ) ,  HEX ) ) ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                if ( ! mSys - > BufCtrl . empty ( ) )  {  
			
		
	
		
			
				
					                    if ( mConfig . serialDebug )  
			
		
	
		
			
				
					                if   ( ! mSys - > BufCtrl . empty ( ) )  {  
			
		
	
		
			
				
					                    if   ( mConfig . serialDebug )  
			
		
	
		
			
				
					                        DPRINTLN ( DBG_DEBUG ,  F ( " recbuf not empty! # " )  +  String ( mSys - > BufCtrl . getFill ( ) ) ) ;  
			
		
	
		
			
				
					                }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                int8_t  maxLoop  =  MAX_NUM_INVERTERS ;  
			
		
	
		
			
				
					                Inverter < >  * iv  =  mSys - > getInverterByPos ( mSendLastIvId ) ;  
			
		
	
		
			
				
					                do  {  
			
		
	
		
			
				
					                    //if(NULL != iv)
  
			
		
	
		
			
				
					                    //  if(NULL != iv)
  
			
		
	
		
			
				
					                    //     mPayload[iv->id].requested = false;
  
			
		
	
		
			
				
					                    mSendLastIvId  =  ( ( MAX_NUM_INVERTERS - 1 )  = =  mSendLastIvId )  ?  0  :  mSendLastIvId  +  1 ;  
			
		
	
		
			
				
					                    mSendLastIvId  =  ( ( MAX_NUM_INVERTERS   -   1 )  = =  mSendLastIvId )  ?  0  :  mSendLastIvId  +  1 ;  
			
		
	
		
			
				
					                    iv  =  mSys - > getInverterByPos ( mSendLastIvId ) ;  
			
		
	
		
			
				
					                }  while ( ( NULL  = =  iv )  & &  ( ( maxLoop - - )  >  0 ) ) ;  
			
		
	
		
			
				
					                }  while   ( ( NULL  = =  iv )  & &  ( ( maxLoop - - )  >  0 ) ) ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                if ( NULL  ! =  iv )  {  
			
		
	
		
			
				
					                    if ( ! mPayload [ iv - > id ] . complete )  
			
		
	
		
			
				
					                if   ( NULL  ! =  iv )  {  
			
		
	
		
			
				
					                    if   ( ! mPayload [ iv - > id ] . complete )  
			
		
	
		
			
				
					                        processPayload ( false ) ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                    if ( ! mPayload [ iv - > id ] . complete )  {  
			
		
	
		
			
				
					                        if ( 0  = =  mPayload [ iv - > id ] . maxPackId )  
			
		
	
		
			
				
					                    if   ( ! mPayload [ iv - > id ] . complete )  {  
			
		
	
		
			
				
					                        if   ( 0  = =  mPayload [ iv - > id ] . maxPackId )  
			
		
	
		
			
				
					                            mStat . rxFailNoAnser + + ;  
			
		
	
		
			
				
					                        else  
			
		
	
		
			
				
					                            mStat . rxFail + + ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                        iv - > setQueuedCmdFinished ( ) ;   // command failed
  
			
		
	
		
			
				
					                        if ( mConfig . serialDebug )  
			
		
	
		
			
				
					                        if   ( mConfig . serialDebug )  
			
		
	
		
			
				
					                            DPRINTLN ( DBG_INFO ,  F ( " enqueued cmd failed/timeout " ) ) ;  
			
		
	
		
			
				
					                        if ( mConfig . serialDebug )  {  
			
		
	
		
			
				
					                        if   ( mConfig . serialDebug )  {  
			
		
	
		
			
				
					                            DPRINT ( DBG_INFO ,  F ( " Inverter # " )  +  String ( iv - > id )  +  "   " ) ;  
			
		
	
		
			
				
					                            DPRINTLN ( DBG_INFO ,  F ( " no Payload received! (retransmits:  " )  +  String ( mPayload [ iv - > id ] . retransmits )  +  " ) " ) ;  
			
		
	
		
			
				
					                        }  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -263,109 +263,101 @@ void app::loop(void) { 
			
		
	
		
			
				
					                    mPayload [ iv - > id ] . requested  =  true ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                    yield ( ) ;  
			
		
	
		
			
				
					                    if ( mConfig . serialDebug )  {  
			
		
	
		
			
				
					                    if   ( mConfig . serialDebug )  {  
			
		
	
		
			
				
					                        DPRINTLN ( DBG_DEBUG ,  F ( " app:loop WiFi WiFi.status  " )  +  String ( WiFi . status ( ) ) ) ;  
			
		
	
		
			
				
					                        DPRINTLN ( DBG_INFO ,  F ( " Requesting Inverter SN  " )  +  String ( iv - > serial . u64 ,  HEX ) ) ;  
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					                    if ( iv - > devControlRequest )  {  
			
		
	
		
			
				
					                        if ( mConfig . serialDebug )  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                    if  ( iv - > devControlRequest )  {  
			
		
	
		
			
				
					                        if  ( mConfig . serialDebug )  
			
		
	
		
			
				
					                            DPRINTLN ( DBG_INFO ,  F ( " Devcontrol request  " )  +  String ( iv - > devControlCmd )  +  F ( "  power limit  " )  +  String ( iv - > powerLimit [ 0 ] ) ) ;  
			
		
	
		
			
				
					                        mSys - > Radio . sendControlPacket ( iv - > radioId . u64 ,  iv - > devControlCmd ,  iv - > powerLimit ) ;  
			
		
	
		
			
				
					                        mPayload [ iv - > id ] . txCmd  =  iv - > devControlCmd ;  
			
		
	
		
			
				
					                        iv - > clearCmdQueue ( ) ;  
			
		
	
		
			
				
					                        iv - > enqueCommand < InfoCommand > ( SystemConfigPara ) ;  
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					                    else  {  
			
		
	
		
			
				
					                    }  else  {  
			
		
	
		
			
				
					                        uint8_t  cmd  =  iv - > getQueuedCmd ( ) ;  
			
		
	
		
			
				
					                        mSys - > Radio . sendTimePacket ( iv - > radioId . u64 ,  cmd ,  mPayload [ iv - > id ] . ts ,  iv - > alarmMesIndex ) ;  
			
		
	
		
			
				
					                        mPayload [ iv - > id ] . txCmd  =  cmd ;  
			
		
	
		
			
				
					                        mRxTicker  =  0 ;  
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					                }  
			
		
	
		
			
				
					            }  
			
		
	
		
			
				
					            else  if ( mConfig . serialDebug )  
			
		
	
		
			
				
					            }  else  if  ( mConfig . serialDebug )  
			
		
	
		
			
				
					                DPRINTLN ( DBG_WARN ,  F ( " Time not set or it is night time, therefore no communication to the inverter! " ) ) ;  
			
		
	
		
			
				
					            yield ( ) ;  
			
		
	
		
			
				
					        }  
			
		
	
		
			
				
					    }  
			
		
	
		
			
				
					}  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					//-----------------------------------------------------------------------------
  
			
		
	
		
			
				
					void  app : : handleIntr ( void )  {  
			
		
	
		
			
				
					    DPRINTLN ( DBG_VERBOSE ,  F ( " app::handleIntr " ) ) ;  
			
		
	
		
			
				
					    mSys - > Radio . handleIntr ( ) ;  
			
		
	
		
			
				
					}  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					//-----------------------------------------------------------------------------
  
			
		
	
		
			
				
					bool  app : : buildPayload ( uint8_t  id )  {  
			
		
	
		
			
				
					    DPRINTLN ( DBG_VERBOSE ,  F ( " app::buildPayload " ) ) ;  
			
		
	
		
			
				
					    uint16_t  crc  =  0xffff ,  crcRcv  =  0x0000 ;  
			
		
	
		
			
				
					    if ( mPayload [ id ] . maxPackId  >  MAX_PAYLOAD_ENTRIES )  
			
		
	
		
			
				
					    if   ( mPayload [ id ] . maxPackId  >  MAX_PAYLOAD_ENTRIES )  
			
		
	
		
			
				
					        mPayload [ id ] . maxPackId  =  MAX_PAYLOAD_ENTRIES ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    for ( uint8_t  i  =  0 ;  i  <  mPayload [ id ] . maxPackId ;  i   + + )  {  
			
		
	
		
			
				
					        if ( mPayload [ id ] . len [ i ]  >  0 )  {  
			
		
	
		
			
				
					            if ( i  = =  ( mPayload [ id ] . maxPackId - 1 ) )  {  
			
		
	
		
			
				
					    for   ( uint8_t  i  =  0 ;  i  <  mPayload [ id ] . maxPackId ;  i + + )  {  
			
		
	
		
			
				
					        if   ( mPayload [ id ] . len [ i ]  >  0 )  {  
			
		
	
		
			
				
					            if   ( i  = =  ( mPayload [ id ] . maxPackId   -   1 ) )  {  
			
		
	
		
			
				
					                crc  =  ah : : crc16 ( mPayload [ id ] . data [ i ] ,  mPayload [ id ] . len [ i ]  -  2 ,  crc ) ;  
			
		
	
		
			
				
					                crcRcv  =  ( mPayload [ id ] . data [ i ] [ mPayload [ id ] . len [ i ]  -  2 ]  < <  8 )  
			
		
	
		
			
				
					                    |  ( mPayload [ id ] . data [ i ] [ mPayload [ id ] . len [ i ]  -  1 ] ) ;  
			
		
	
		
			
				
					            }  
			
		
	
		
			
				
					            else  
			
		
	
		
			
				
					                crcRcv  =  ( mPayload [ id ] . data [ i ] [ mPayload [ id ] . len [ i ]  -  2 ]  < <  8 )  |  ( mPayload [ id ] . data [ i ] [ mPayload [ id ] . len [ i ]  -  1 ] ) ;  
			
		
	
		
			
				
					            }  else  
			
		
	
		
			
				
					                crc  =  ah : : crc16 ( mPayload [ id ] . data [ i ] ,  mPayload [ id ] . len [ i ] ,  crc ) ;  
			
		
	
		
			
				
					        }  
			
		
	
		
			
				
					        yield ( ) ;  
			
		
	
		
			
				
					    }  
			
		
	
		
			
				
					    if ( crc  = =  crcRcv )  
			
		
	
		
			
				
					        return  true ;  
			
		
	
		
			
				
					    return  false ;  
			
		
	
		
			
				
					}  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    return  ( crc  = =  crcRcv )  ?  true  :  false ;  
			
		
	
		
			
				
					}  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					//-----------------------------------------------------------------------------
  
			
		
	
		
			
				
					void  app : : processPayload ( bool  retransmit )  {  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					# ifdef __MQTT_AFTER_RX__  
			
		
	
		
			
				
					    boolean  doMQTT  =  false ;  
			
		
	
		
			
				
					# endif  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    //DPRINTLN(DBG_INFO, F("processPayload"));
  
			
		
	
		
			
				
					    for ( uint8_t  id  =  0 ;  id  <  mSys - > getNumInverters ( ) ;  id + + )  {  
			
		
	
		
			
				
					    //  DPRINTLN(DBG_INFO, F("processPayload"));
  
			
		
	
		
			
				
					    for   ( uint8_t  id  =  0 ;  id  <  mSys - > getNumInverters ( ) ;  id + + )  {  
			
		
	
		
			
				
					        Inverter < >  * iv  =  mSys - > getInverterByPos ( id ) ;  
			
		
	
		
			
				
					        if ( NULL  ! =  iv )  {  
			
		
	
		
			
				
					            if ( ( mPayload [ iv - > id ] . txId  ! =  ( TX_REQ_INFO  +  0x80 ) )  & &  ( 0  ! =  mPayload [ iv - > id ] . txId ) )  {  
			
		
	
		
			
				
					        if   ( NULL  ! =  iv )  {  
			
		
	
		
			
				
					            if   ( ( mPayload [ iv - > id ] . txId  ! =  ( TX_REQ_INFO  +  ALL_FRAMES ) )  & &  ( 0  ! =  mPayload [ iv - > id ] . txId ) )  {  
			
		
	
		
			
				
					                // no processing needed if txId is not 0x95
  
			
		
	
		
			
				
					                //DPRINTLN(DBG_INFO, F("processPayload - set complete, txId: ") + String(mPayload[iv->id].txId, HEX));
  
			
		
	
		
			
				
					                //  DPRINTLN(DBG_INFO, F("processPayload - set complete, txId: ") + String(mPayload[iv->id].txId, HEX));
  
			
		
	
		
			
				
					                mPayload [ iv - > id ] . complete  =  true ;  
			
		
	
		
			
				
					            }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					            if ( ! mPayload [ iv - > id ] . complete  )  {  
			
		
	
		
			
				
					                if ( ! buildPayload ( iv - > id ) )  {  // payload not complete
  
			
		
	
		
			
				
					                    if ( mPayload [ iv - > id ] . requested )  {  
			
		
	
		
			
				
					                        if ( retransmit )  {  
			
		
	
		
			
				
					                            if ( iv - > devControlCmd  = =  Restart  | |  iv - > devControlCmd  = =  CleanState_LockAndAlarm  )  {  
			
		
	
		
			
				
					            if  ( ! mPayload [ iv - > id ] . complete )  {  
			
		
	
		
			
				
					                if  ( ! buildPayload ( iv - > id ) )   // payload not complete
  
			
		
	
		
			
				
					                {  
			
		
	
		
			
				
					                    if  ( mPayload [ iv - > id ] . requested )  {  
			
		
	
		
			
				
					                        if  ( retransmit )  {  
			
		
	
		
			
				
					                            if  ( iv - > devControlCmd  = =  Restart  | |  iv - > devControlCmd  = =  CleanState_LockAndAlarm )  {  
			
		
	
		
			
				
					                                // This is required to prevent retransmissions without answer.
  
			
		
	
		
			
				
					                                DPRINTLN ( DBG_INFO ,  F ( " Prevent retransmit on Restart / CleanState_LockAndAlarm... " ) ) ;  
			
		
	
		
			
				
					                                mPayload [ iv - > id ] . retransmits  =  mConfig . maxRetransPerPyld ;  
			
		
	
		
			
				
					                            }  else  {  
			
		
	
		
			
				
					                                if ( mPayload [ iv - > id ] . retransmits  <  mConfig . maxRetransPerPyld )  {  
			
		
	
		
			
				
					                                if   ( mPayload [ iv - > id ] . retransmits  <  mConfig . maxRetransPerPyld )  {  
			
		
	
		
			
				
					                                    mPayload [ iv - > id ] . retransmits + + ;  
			
		
	
		
			
				
					                                    if ( mPayload [ iv - > id ] . maxPackId  ! =  0 )  {  
			
		
	
		
			
				
					                                        for ( uint8_t  i  =  0 ;  i  <  ( mPayload [ iv - > id ] . maxPackId - 1 ) ;  i + + )  {  
			
		
	
		
			
				
					                                            if ( mPayload [ iv - > id ] . len [ i ]  = =  0 )  {  
			
		
	
		
			
				
					                                                if ( mConfig . serialDebug )  
			
		
	
		
			
				
					                                                    DPRINTLN ( DBG_WARN ,  F ( " while retrieving data: Frame  " )  +  String ( i + 1 )  +  F ( "  missing: Request Retransmit " ) ) ;  
			
		
	
		
			
				
					                                                mSys - > Radio . sendCmdPacket ( iv - > radioId . u64 ,  TX_REQ_INFO ,  ( SINGLE_FRAME + i ) ,  true ) ;  
			
		
	
		
			
				
					                                    if   ( mPayload [ iv - > id ] . maxPackId  ! =  0 )  {  
			
		
	
		
			
				
					                                        for   ( uint8_t  i  =  0 ;  i  <  ( mPayload [ iv - > id ] . maxPackId   -   1 ) ;  i + + )  {  
			
		
	
		
			
				
					                                            if   ( mPayload [ iv - > id ] . len [ i ]  = =  0 )  {  
			
		
	
		
			
				
					                                                if   ( mConfig . serialDebug )  
			
		
	
		
			
				
					                                                    DPRINTLN ( DBG_WARN ,  F ( " while retrieving data: Frame  " )  +  String ( i   +   1 )  +  F ( "  missing: Request Retransmit " ) ) ;  
			
		
	
		
			
				
					                                                mSys - > Radio . sendCmdPacket ( iv - > radioId . u64 ,  TX_REQ_INFO ,  ( SINGLE_FRAME   +   i ) ,  true ) ;  
			
		
	
		
			
				
					                                                break ;   // only retransmit one frame per loop
  
			
		
	
		
			
				
					                                            }  
			
		
	
		
			
				
					                                            yield ( ) ;  
			
		
	
		
			
				
					                                        }  
			
		
	
		
			
				
					                                    }  
			
		
	
		
			
				
					                                    else  {  
			
		
	
		
			
				
					                                        if ( mConfig . serialDebug )  
			
		
	
		
			
				
					                                    }  else  {  
			
		
	
		
			
				
					                                        if  ( mConfig . serialDebug )  
			
		
	
		
			
				
					                                            DPRINTLN ( DBG_WARN ,  F ( " while retrieving data: last frame missing: Request Retransmit " ) ) ;  
			
		
	
		
			
				
					                                        if ( 0x00  ! =  mLastPacketId )  
			
		
	
		
			
				
					                                        if   ( 0x00  ! =  mLastPacketId )  
			
		
	
		
			
				
					                                            mSys - > Radio . sendCmdPacket ( iv - > radioId . u64 ,  TX_REQ_INFO ,  mLastPacketId ,  true ) ;  
			
		
	
		
			
				
					                                        else  {  
			
		
	
		
			
				
					                                            mPayload [ iv - > id ] . txCmd  =  iv - > getQueuedCmd ( ) ;  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -377,8 +369,7 @@ void app::processPayload(bool retransmit) { 
			
		
	
		
			
				
					                            }  
			
		
	
		
			
				
					                        }  
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					                }  
			
		
	
		
			
				
					                else  {  // payload complete
  
			
		
	
		
			
				
					                }  else  {   // payload complete
  
			
		
	
		
			
				
					                    DPRINTLN ( DBG_INFO ,  F ( " procPyld: cmd:   " )  +  String ( mPayload [ iv - > id ] . txCmd ) ) ;  
			
		
	
		
			
				
					                    DPRINTLN ( DBG_INFO ,  F ( " procPyld: txid: 0x " )  +  String ( mPayload [ iv - > id ] . txId ,  HEX ) ) ;  
			
		
	
		
			
				
					                    DPRINTLN ( DBG_DEBUG ,  F ( " procPyld: max:   " )  +  String ( mPayload [ iv - > id ] . maxPackId ) ) ;  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -390,33 +381,33 @@ void app::processPayload(bool retransmit) { 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                    memset ( payload ,  0 ,  128 ) ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                    for ( uint8_t  i  =  0 ;  i  <  ( mPayload [ iv - > id ] . maxPackId ) ;  i   + + )  {  
			
		
	
		
			
				
					                    for   ( uint8_t  i  =  0 ;  i  <  ( mPayload [ iv - > id ] . maxPackId ) ;  i + + )  {  
			
		
	
		
			
				
					                        memcpy ( & payload [ payloadLen ] ,  mPayload [ iv - > id ] . data [ i ] ,  ( mPayload [ iv - > id ] . len [ i ] ) ) ;  
			
		
	
		
			
				
					                        payloadLen  + =  ( mPayload [ iv - > id ] . len [ i ] ) ;  
			
		
	
		
			
				
					                        yield ( ) ;  
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					                    payloadLen - = 2 ;  
			
		
	
		
			
				
					                    payloadLen   - =   2 ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                    if ( mConfig . serialDebug )  {  
			
		
	
		
			
				
					                    if   ( mConfig . serialDebug )  {  
			
		
	
		
			
				
					                        DPRINT ( DBG_INFO ,  F ( " Payload ( " )  +  String ( payloadLen )  +  " ):  " ) ;  
			
		
	
		
			
				
					                        mSys - > Radio . dumpBuf ( NULL ,  payload ,  payloadLen ) ;  
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                    if ( NULL  = =  rec )  
			
		
	
		
			
				
					                    if   ( NULL  = =  rec )  {   
			
		
	
		
			
				
					                        DPRINTLN ( DBG_ERROR ,  F ( " record is NULL! " ) ) ;  
			
		
	
		
			
				
					                    else  if ( ( rec - > pyldLen  = =  payloadLen )  | |  ( 0  = =  rec - > pyldLen ) )  {  
			
		
	
		
			
				
					                        if ( mPayload [ iv - > id ] . txId  = =  ( TX_REQ_INFO  +  0x80 ) )  
			
		
	
		
			
				
					                    }  else  if   ( ( rec - > pyldLen  = =  payloadLen )  | |  ( 0  = =  rec - > pyldLen ) )  {  
			
		
	
		
			
				
					                        if   ( mPayload [ iv - > id ] . txId  = =  ( TX_REQ_INFO  +  0x80 ) )  
			
		
	
		
			
				
					                            mStat . rxSuccess + + ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                        rec - > ts  =  mPayload [ iv - > id ] . ts ;  
			
		
	
		
			
				
					                        for ( uint8_t  i  =  0 ;  i  <  rec - > length ;  i + + )  {  
			
		
	
		
			
				
					                        for   ( uint8_t  i  =  0 ;  i  <  rec - > length ;  i + + )  {  
			
		
	
		
			
				
					                            iv - > addValue ( i ,  payload ,  rec ) ;  
			
		
	
		
			
				
					                            yield ( ) ;  
			
		
	
		
			
				
					                        }  
			
		
	
		
			
				
					                        iv - > doCalculations ( ) ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                        // MQTT send out
  
			
		
	
		
			
				
					                        if ( mMqttActive )  {  
			
		
	
		
			
				
					                        if   ( mMqttActive )  {  
			
		
	
		
			
				
					                            record_t < >  * recRealtime  =  iv - > getRecordStruct ( RealTimeRunData_Debug ) ;  
			
		
	
		
			
				
					                            char  topic [ 32  +  MAX_NAME_LENGTH ] ,  val [ 32 ] ;  
			
		
	
		
			
				
					                            float  total [ 4 ] ;  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -429,33 +420,42 @@ void app::processPayload(bool retransmit) { 
			
		
	
		
			
				
					                                            snprintf ( topic ,  32  +  MAX_NAME_LENGTH ,  " %s/ch%d/%s " ,  iv - > name ,  rec - > assign [ i ] . ch ,  fields [ rec - > assign [ i ] . fieldId ] ) ;  
			
		
	
		
			
				
					                                            snprintf ( val ,  10 ,  " %.3f " ,  iv - > getValue ( i ,  rec ) ) ;  
			
		
	
		
			
				
					                                            mMqtt . sendMsg ( topic ,  val ) ;  
			
		
	
		
			
				
					                                            if ( recRealtime  = =  rec )  {  
			
		
	
		
			
				
					                                                if ( CH0  = =  rec - > assign [ i ] . ch )  {  
			
		
	
		
			
				
					                                                    switch ( rec - > assign [ i ] . fieldId )  {  
			
		
	
		
			
				
					                                                        case  FLD_PAC :  total [ 0 ]  + =  iv - > getValue ( i ,  rec ) ;  break ;  
			
		
	
		
			
				
					                                                        case  FLD_YT :   total [ 1 ]  + =  iv - > getValue ( i ,  rec ) ;  break ;  
			
		
	
		
			
				
					                                                        case  FLD_YD :   total [ 2 ]  + =  iv - > getValue ( i ,  rec ) ;  break ;  
			
		
	
		
			
				
					                                                        case  FLD_PDC :  total [ 3 ]  + =  iv - > getValue ( i ,  rec ) ;  break ;  
			
		
	
		
			
				
					                                            if  ( recRealtime  = =  rec )  {  
			
		
	
		
			
				
					                                                if  ( CH0  = =  rec - > assign [ i ] . ch )  {  
			
		
	
		
			
				
					                                                    switch  ( rec - > assign [ i ] . fieldId )  {  
			
		
	
		
			
				
					                                                        case  FLD_PAC :  
			
		
	
		
			
				
					                                                            total [ 0 ]  + =  iv - > getValue ( i ,  rec ) ;  
			
		
	
		
			
				
					                                                            break ;  
			
		
	
		
			
				
					                                                        case  FLD_YT :  
			
		
	
		
			
				
					                                                            total [ 1 ]  + =  iv - > getValue ( i ,  rec ) ;  
			
		
	
		
			
				
					                                                            break ;  
			
		
	
		
			
				
					                                                        case  FLD_YD :  
			
		
	
		
			
				
					                                                            total [ 2 ]  + =  iv - > getValue ( i ,  rec ) ;  
			
		
	
		
			
				
					                                                            break ;  
			
		
	
		
			
				
					                                                        case  FLD_PDC :  
			
		
	
		
			
				
					                                                            total [ 3 ]  + =  iv - > getValue ( i ,  rec ) ;  
			
		
	
		
			
				
					                                                            break ;  
			
		
	
		
			
				
					                                                    }  
			
		
	
		
			
				
					                                                }  
			
		
	
		
			
				
					                                            }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                                            if ( iv - > isProducing ( mUtcTimestamp ,  rec ) ) {  
			
		
	
		
			
				
					                                            if   ( iv - > isProducing ( mUtcTimestamp ,  rec ) )   {  
			
		
	
		
			
				
					                                                snprintf ( topic ,  32  +  MAX_NAME_LENGTH ,  " %s/available_text " ,  iv - > name ) ;  
			
		
	
		
			
				
					                                                snprintf ( val ,  32 ,  DEF_MQTT_IV_MESSAGE_INVERTER_AVAIL_AND_PRODUCED ) ;  
			
		
	
		
			
				
					                                                mMqtt . sendMsg ( topic ,  val ) ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                                                snprintf ( topic ,  32  +  MAX_NAME_LENGTH ,  " %s/available " ,  iv - > name ) ;  
			
		
	
		
			
				
					                                                snprintf ( val ,  32 ,  " 2 " ) ;  
			
		
	
		
			
				
					                                                mMqtt . sendMsg ( topic ,  val ) ;  
			
		
	
		
			
				
					                                            }  else  {  
			
		
	
		
			
				
					                                                snprintf ( topic ,  32  +  MAX_NAME_LENGTH ,  " %s/available_text " ,  iv - > name ) ;  
			
		
	
		
			
				
					                                                snprintf ( val ,  32 ,  DEF_MQTT_IV_MESSAGE_INVERTER_AVAIL_AND_NOT_PRODUCED ) ;  
			
		
	
		
			
				
					                                                mMqtt . sendMsg ( topic ,  val ) ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                                                snprintf ( topic ,  32  +  MAX_NAME_LENGTH ,  " %s/available " ,  iv - > name ) ;  
			
		
	
		
			
				
					                                                snprintf ( val ,  32 ,  " 1 " ) ;  
			
		
	
		
			
				
					                                                mMqtt . sendMsg ( topic ,  val ) ;  
			
		
	
		
			
				
					                                            }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                                            mMqtt . sendMsg ( topic ,  val ) ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                                            snprintf ( topic ,  32  +  MAX_NAME_LENGTH ,  " %s/last_success " ,  iv - > name ) ;  
			
		
	
		
			
				
					                                            snprintf ( val ,  48 ,  " %i " ,  iv - > getLastTs ( rec )  *  1000 ) ;  
			
		
	
		
			
				
					                                            mMqtt . sendMsg ( topic ,  val ) ;  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -467,15 +467,23 @@ void app::processPayload(bool retransmit) { 
			
		
	
		
			
				
					                            }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                            // total values (sum of all inverters)
  
			
		
	
		
			
				
					                            if ( recRealtime  = =  rec )  {  
			
		
	
		
			
				
					                                if ( mSys - > getNumInverters ( )  >  1 )  {  
			
		
	
		
			
				
					                            if   ( recRealtime  = =  rec )  {  
			
		
	
		
			
				
					                                if   ( mSys - > getNumInverters ( )  >  1 )  {  
			
		
	
		
			
				
					                                    uint8_t  fieldId  =  0 ;  
			
		
	
		
			
				
					                                    for  ( uint8_t  i  =  0 ;  i  <  4 ;  i + + )  {  
			
		
	
		
			
				
					                                        switch ( i )  {  
			
		
	
		
			
				
					                                            case  0 :  fieldId  =  FLD_PAC ;  break ;  
			
		
	
		
			
				
					                                            case  1 :  fieldId  =  FLD_YT ;   break ;  
			
		
	
		
			
				
					                                            case  2 :  fieldId  =  FLD_YD ;   break ;  
			
		
	
		
			
				
					                                            case  3 :  fieldId  =  FLD_PDC ;  break ;  
			
		
	
		
			
				
					                                        switch  ( i )  {  
			
		
	
		
			
				
					                                            case  0 :  
			
		
	
		
			
				
					                                                fieldId  =  FLD_PAC ;  
			
		
	
		
			
				
					                                                break ;  
			
		
	
		
			
				
					                                            case  1 :  
			
		
	
		
			
				
					                                                fieldId  =  FLD_YT ;  
			
		
	
		
			
				
					                                                break ;  
			
		
	
		
			
				
					                                            case  2 :  
			
		
	
		
			
				
					                                                fieldId  =  FLD_YD ;  
			
		
	
		
			
				
					                                                break ;  
			
		
	
		
			
				
					                                            case  3 :  
			
		
	
		
			
				
					                                                fieldId  =  FLD_PDC ;  
			
		
	
		
			
				
					                                                break ;  
			
		
	
		
			
				
					                                        }  
			
		
	
		
			
				
					                                        snprintf ( topic ,  32  +  MAX_NAME_LENGTH ,  " total/%s " ,  fields [ fieldId ] ) ;  
			
		
	
		
			
				
					                                        snprintf ( val ,  10 ,  " %.3f " ,  total [ i ] ) ;  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -484,8 +492,7 @@ void app::processPayload(bool retransmit) { 
			
		
	
		
			
				
					                                }  
			
		
	
		
			
				
					                            }  
			
		
	
		
			
				
					                        }  
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					                    else  {  
			
		
	
		
			
				
					                    }  else  {  
			
		
	
		
			
				
					                        DPRINTLN ( DBG_ERROR ,  F ( " plausibility check failed, expected  " )  +  String ( rec - > pyldLen )  +  F ( "  bytes " ) ) ;  
			
		
	
		
			
				
					                        mStat . rxFail + + ;  
			
		
	
		
			
				
					                    }  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -507,87 +514,104 @@ void app::processPayload(bool retransmit) { 
			
		
	
		
			
				
					    //  dann die den mMqttTicker auf mMqttIntervall -2 setzen, also
  
			
		
	
		
			
				
					    //  MQTT aussenden in 2 sek aktivieren
  
			
		
	
		
			
				
					    //  dies sollte noch über einen Schalter im Setup aktivier / deaktivierbar gemacht werden
  
			
		
	
		
			
				
					    if (   ( mMqttInterval  ! =  0xffff )  & &  doMQTT   )  {  
			
		
	
		
			
				
					        + + mMqttTicker  =  mMqttInterval  - 2 ;  
			
		
	
		
			
				
					        DPRINT ( DBG_DEBUG ,  F ( " MQTTticker auf Intervall -2 sec  " ) )   ;  
			
		
	
		
			
				
					    if   ( ( mMqttInterval  ! =  0xffff )  & &  doMQTT )  {  
			
		
	
		
			
				
					        + + mMqttTicker  =  mMqttInterval  -   2 ;  
			
		
	
		
			
				
					        DPRINT ( DBG_DEBUG ,  F ( " MQTTticker auf Intervall -2 sec  " ) ) ;  
			
		
	
		
			
				
					    }  
			
		
	
		
			
				
					# endif  
			
		
	
		
			
				
					}  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					//-----------------------------------------------------------------------------
  
			
		
	
		
			
				
					void  app : : cbMqtt ( char *   topic ,  byte *   payload ,  unsigned  int  length )  {  
			
		
	
		
			
				
					void  app : : cbMqtt ( char   * topic ,  byte   * payload ,  unsigned  int  length )  {  
			
		
	
		
			
				
					    // callback handling on subscribed devcontrol topic
  
			
		
	
		
			
				
					    DPRINTLN ( DBG_INFO ,  F ( " app::cbMqtt " ) ) ;  
			
		
	
		
			
				
					    // subcribed topics are mTopic + "/devcontrol/#" where # is <inverter_id>/<subcmd in dec>
  
			
		
	
		
			
				
					    // eg. mypvsolar/devcontrol/1/11 with payload "400" --> inverter 1 active power limit 400 Watt
  
			
		
	
		
			
				
					    const  char  * token  =  strtok ( topic ,  " / " ) ;  
			
		
	
		
			
				
					    while  ( token  ! =  NULL )  
			
		
	
		
			
				
					    {     
			
		
	
		
			
				
					        if  ( strcmp ( token , " devcontrol " ) = = 0 ) {  
			
		
	
		
			
				
					    while  ( token  ! =  NULL )  {  
			
		
	
		
			
				
					        if  ( strcmp ( token ,  " devcontrol " )  = =  0 )  {  
			
		
	
		
			
				
					            token  =  strtok ( NULL ,  " / " ) ;  
			
		
	
		
			
				
					            uint8_t  iv_id  =  std : : stoi ( token ) ;  
			
		
	
		
			
				
					            if  ( iv_id  > =  0   & &  iv_id  < =  MAX_NUM_INVERTERS ) {  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					            if  ( iv_id  > =  0  & &  iv_id  < =  MAX_NUM_INVERTERS )  {  
			
		
	
		
			
				
					                Inverter < >  * iv  =  this - > mSys - > getInverterByPos ( iv_id ) ;  
			
		
	
		
			
				
					                if ( NULL  ! =  iv )  {  
			
		
	
		
			
				
					                    if  ( ! iv - > devControlRequest )  {  // still pending
  
			
		
	
		
			
				
					                if  ( NULL  ! =  iv )  {  
			
		
	
		
			
				
					                    if  ( ! iv - > devControlRequest )   // still pending
  
			
		
	
		
			
				
					                    {  
			
		
	
		
			
				
					                        token  =  strtok ( NULL ,  " / " ) ;  
			
		
	
		
			
				
					                        switch  (  std : : stoi ( token )  ) {  
			
		
	
		
			
				
					                            case  ActivePowerContr :   // Active Power Control
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                        switch  ( std : : stoi ( token ) )  {  
			
		
	
		
			
				
					                            // Active Power Control
  
			
		
	
		
			
				
					                            case  ActivePowerContr :  
			
		
	
		
			
				
					                                token  =  strtok ( NULL ,  " / " ) ;   // get ControlMode aka "PowerPF.Desc" in DTU-Pro Code from topic string
  
			
		
	
		
			
				
					                                if  ( token  = =  NULL )           // default via mqtt ommit the LimitControlMode
  
			
		
	
		
			
				
					                                    iv - > powerLimit [ 1 ]  =  AbsolutNonPersistent ;  
			
		
	
		
			
				
					                                else  
			
		
	
		
			
				
					                                    iv - > powerLimit [ 1 ]  =  std : : stoi ( token ) ;  
			
		
	
		
			
				
					                                if  ( length < = 5 ) {  // if (std::stoi((char*)payload) > 0) more error handling powerlimit needed?
  
			
		
	
		
			
				
					                                    if  ( iv - > powerLimit [ 1 ]  > =  AbsolutNonPersistent  & &  iv - > powerLimit [ 1 ]  < =  RelativPersistent ) {  
			
		
	
		
			
				
					                                if  ( length   < =   5 )   {    // if (std::stoi((char*)payload) > 0) more error handling powerlimit needed?
  
			
		
	
		
			
				
					                                    if  ( iv - > powerLimit [ 1 ]  > =  AbsolutNonPersistent  & &  iv - > powerLimit [ 1 ]  < =  RelativPersistent )   {  
			
		
	
		
			
				
					                                        iv - > devControlCmd  =  ActivePowerContr ;  
			
		
	
		
			
				
					                                        iv - > powerLimit [ 0 ]  =  std : : stoi ( std : : string ( ( char * ) payload ,  ( unsigned  int ) length ) ) ;  // THX to @silversurfer
  
			
		
	
		
			
				
					                                        if  ( iv - > powerLimit [ 1 ]  &  0x0001 )  
			
		
	
		
			
				
					                                            DPRINTLN ( DBG_INFO ,  F ( " Power limit for inverter  " )  +  String ( iv - > id )  +  F ( "  set to  " )  +  String ( iv - > powerLimit [ 0 ] )  +  F ( " % " )   ) ;       
			
		
	
		
			
				
					                                        iv - > powerLimit [ 0 ]  =  std : : stoi ( std : : string ( ( char   * ) payload ,  ( unsigned  int ) length ) ) ;    // THX to @silversurfer
  
			
		
	
		
			
				
					                                        /*if (iv->powerLimit[1] & 0x0001)
  
			
		
	
		
			
				
					                                            DPRINTLN ( DBG_INFO ,  F ( " Power limit for inverter  " )  +  String ( iv - > id )  +  F ( "  set to  " )  +  String ( iv - > powerLimit [ 0 ] )  +  F ( " % " ) ) ;  
			
		
	
		
			
				
					                                        else  
			
		
	
		
			
				
					                                            DPRINTLN ( DBG_INFO ,  F ( " Power limit for inverter  " )  +  String ( iv - > id )  +  F ( "  set to  " )  +  String ( iv - > powerLimit [ 0 ] )  +  F ( " W " )  ) ;  
			
		
	
		
			
				
					                                            DPRINTLN ( DBG_INFO ,  F ( " Power limit for inverter  " )  +  String ( iv - > id )  +  F ( "  set to  " )  +  String ( iv - > powerLimit [ 0 ] )  +  F ( " W " ) ) ; */  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                                        DPRINTLN ( DBG_INFO ,  F ( " Power limit for inverter  " )  +  String ( iv - > id )  +  F ( "  set to  " )  +  String ( iv - > powerLimit [ 0 ] )  +  F ( ( iv - > powerLimit [ 1 ]  &  0x0001 )  ?  " % "  :  " W " ) ) ;  
			
		
	
		
			
				
					                                    }  
			
		
	
		
			
				
					                                    iv - > devControlRequest  =  true ;  
			
		
	
		
			
				
					                                }  else  {  
			
		
	
		
			
				
					                                    DPRINTLN ( DBG_INFO ,  F ( " Invalid mqtt payload recevied:  " )  +  String ( ( char * ) payload ) ) ;  
			
		
	
		
			
				
					                                    DPRINTLN ( DBG_INFO ,  F ( " Invalid mqtt payload recevied:  " )  +  String ( ( char   * ) payload ) ) ;  
			
		
	
		
			
				
					                                }  
			
		
	
		
			
				
					                                break ;  
			
		
	
		
			
				
					                            case  TurnOn :  // Turn On
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                            // Turn On
  
			
		
	
		
			
				
					                            case  TurnOn :  
			
		
	
		
			
				
					                                iv - > devControlCmd  =  TurnOn ;  
			
		
	
		
			
				
					                                DPRINTLN ( DBG_INFO ,  F ( " Turn on inverter  " )  +  String ( iv - > id )  ) ;  
			
		
	
		
			
				
					                                DPRINTLN ( DBG_INFO ,  F ( " Turn on inverter  " )  +  String ( iv - > id ) ) ;  
			
		
	
		
			
				
					                                iv - > devControlRequest  =  true ;  
			
		
	
		
			
				
					                                break ;  
			
		
	
		
			
				
					                            case  TurnOff :  // Turn Off
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                            // Turn Off
  
			
		
	
		
			
				
					                            case  TurnOff :  
			
		
	
		
			
				
					                                iv - > devControlCmd  =  TurnOff ;  
			
		
	
		
			
				
					                                DPRINTLN ( DBG_INFO ,  F ( " Turn off inverter  " )  +  String ( iv - > id )  ) ;  
			
		
	
		
			
				
					                                DPRINTLN ( DBG_INFO ,  F ( " Turn off inverter  " )  +  String ( iv - > id ) ) ;  
			
		
	
		
			
				
					                                iv - > devControlRequest  =  true ;  
			
		
	
		
			
				
					                                break ;  
			
		
	
		
			
				
					                            case  Restart :  // Restart
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                            // Restart
  
			
		
	
		
			
				
					                            case  Restart :  
			
		
	
		
			
				
					                                iv - > devControlCmd  =  Restart ;  
			
		
	
		
			
				
					                                DPRINTLN ( DBG_INFO ,  F ( " Restart inverter  " )  +  String ( iv - > id )  ) ;  
			
		
	
		
			
				
					                                DPRINTLN ( DBG_INFO ,  F ( " Restart inverter  " )  +  String ( iv - > id ) ) ;  
			
		
	
		
			
				
					                                iv - > devControlRequest  =  true ;  
			
		
	
		
			
				
					                                break ;  
			
		
	
		
			
				
					                            case  ReactivePowerContr :  // Reactive Power Control
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                            // Reactive Power Control
  
			
		
	
		
			
				
					                            case  ReactivePowerContr :  
			
		
	
		
			
				
					                                iv - > devControlCmd  =  ReactivePowerContr ;  
			
		
	
		
			
				
					                                if  ( true ) {  // if (std::stoi((char*)payload) > 0) error handling powerlimit needed?
  
			
		
	
		
			
				
					                                if  ( true )   {    // if (std::stoi((char*)payload) > 0) error handling powerlimit needed?
  
			
		
	
		
			
				
					                                    iv - > devControlCmd  =  ReactivePowerContr ;  
			
		
	
		
			
				
					                                    iv - > powerLimit [ 0 ]  =  std : : stoi ( std : : string ( ( char * ) payload ,  ( unsigned  int ) length ) ) ;  
			
		
	
		
			
				
					                                    iv - > powerLimit [ 0 ]  =  std : : stoi ( std : : string ( ( char   * ) payload ,  ( unsigned  int ) length ) ) ;  
			
		
	
		
			
				
					                                    iv - > powerLimit [ 1 ]  =  0x0000 ;   // if reactivepower limit is set via external interface --> set it temporay
  
			
		
	
		
			
				
					                                    DPRINTLN ( DBG_DEBUG ,  F ( " Reactivepower limit for inverter  " )  +  String ( iv - > id )  +  F ( "  set to  " )  +  String ( iv - > powerLimit [ 0 ] )  +  F ( " W " )   ) ;  
			
		
	
		
			
				
					                                    DPRINTLN ( DBG_DEBUG ,  F ( " Reactivepower limit for inverter  " )  +  String ( iv - > id )  +  F ( "  set to  " )  +  String ( iv - > powerLimit [ 0 ] )  +  F ( " W " ) ) ;  
			
		
	
		
			
				
					                                    iv - > devControlRequest  =  true ;  
			
		
	
		
			
				
					                                }  
			
		
	
		
			
				
					                                break ;  
			
		
	
		
			
				
					                            case  PFSet :  // Set Power Factor
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                            // Set Power Factor
  
			
		
	
		
			
				
					                            case  PFSet :  
			
		
	
		
			
				
					                                // iv->devControlCmd = PFSet;
  
			
		
	
		
			
				
					                                // uint16_t power_factor = std::stoi(strtok(NULL, "/"));
  
			
		
	
		
			
				
					                                DPRINTLN ( DBG_INFO ,  F ( " Set Power Factor not implemented for inverter  " )  +  String ( iv - > id )   ) ;  
			
		
	
		
			
				
					                                DPRINTLN ( DBG_INFO ,  F ( " Set Power Factor not implemented for inverter  " )  +  String ( iv - > id ) ) ;  
			
		
	
		
			
				
					                                break ;  
			
		
	
		
			
				
					                            case  CleanState_LockAndAlarm :  // CleanState lock & alarm
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                            // CleanState lock & alarm
  
			
		
	
		
			
				
					                            case  CleanState_LockAndAlarm :  
			
		
	
		
			
				
					                                iv - > devControlCmd  =  CleanState_LockAndAlarm ;  
			
		
	
		
			
				
					                                 DPRINTLN ( DBG_INFO ,  F ( " CleanState lock & alarm for inverter  " )  +  String ( iv - > id )  ) ;  
			
		
	
		
			
				
					                                DPRINTLN ( DBG_INFO ,  F ( " CleanState lock & alarm for inverter  " )  +  String ( iv - > id ) ) ;  
			
		
	
		
			
				
					                                iv - > devControlRequest  =  true ;  
			
		
	
		
			
				
					                                break ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                            default :  
			
		
	
		
			
				
					                                DPRINTLN ( DBG_INFO ,  " Not implemented " ) ;  
			
		
	
		
			
				
					                                break ;  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -602,13 +626,11 @@ void app::cbMqtt(char* topic, byte* payload, unsigned int length) { 
			
		
	
		
			
				
					    DPRINTLN ( DBG_INFO ,  F ( " app::cbMqtt finished " ) ) ;  
			
		
	
		
			
				
					}  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					//-----------------------------------------------------------------------------
  
			
		
	
		
			
				
					bool  app : : getWifiApActive ( void )  {  
			
		
	
		
			
				
					    return  mWifi - > getApActive ( ) ;  
			
		
	
		
			
				
					}  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					//-----------------------------------------------------------------------------
  
			
		
	
		
			
				
					void  app : : scanAvailNetworks ( void )  {  
			
		
	
		
			
				
					    mWifi - > scanAvailNetworks ( ) ;  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -620,18 +642,17 @@ void app::getAvailNetworks(JsonObject obj) { 
			
		
	
		
			
				
					    mWifi - > getAvailNetworks ( obj ) ;  
			
		
	
		
			
				
					}  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					//-----------------------------------------------------------------------------
  
			
		
	
		
			
				
					void  app : : sendMqttDiscoveryConfig ( void )  {  
			
		
	
		
			
				
					    DPRINTLN ( DBG_VERBOSE ,  F ( " app::sendMqttDiscoveryConfig " ) ) ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    char  stateTopic [ 64 ] ,  discoveryTopic [ 64 ] ,  buffer [ 512 ] ,  name [ 32 ] ,  uniq_id [ 32 ] ;  
			
		
	
		
			
				
					    for ( uint8_t  id  =  0 ;  id  <  mSys - > getNumInverters ( ) ;  id + + )  {  
			
		
	
		
			
				
					    for   ( uint8_t  id  =  0 ;  id  <  mSys - > getNumInverters ( ) ;  id + + )  {  
			
		
	
		
			
				
					        Inverter < >  * iv  =  mSys - > getInverterByPos ( id ) ;  
			
		
	
		
			
				
					        if ( NULL  ! =  iv )  {  
			
		
	
		
			
				
					        if   ( NULL  ! =  iv )  {  
			
		
	
		
			
				
					            record_t < >  * rec  =  iv - > getRecordStruct ( RealTimeRunData_Debug ) ;  
			
		
	
		
			
				
					            // TODO: next line makes no sense if discovery config is send manually by button
  
			
		
	
		
			
				
					            //if(iv->isAvailable(mUtcTimestamp, rec) && mMqttConfigSendState[id] != true) {
  
			
		
	
		
			
				
					            //  if(iv->isAvailable(mUtcTimestamp, rec) && mMqttConfigSendState[id] != true) {
  
			
		
	
		
			
				
					            DynamicJsonDocument  deviceDoc ( 128 ) ;  
			
		
	
		
			
				
					            deviceDoc [ " name " ]  =  iv - > name ;  
			
		
	
		
			
				
					            deviceDoc [ " ids " ]  =  String ( iv - > serial . u64 ,  HEX ) ;  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -641,7 +662,7 @@ void app::sendMqttDiscoveryConfig(void) { 
			
		
	
		
			
				
					            JsonObject  deviceObj  =  deviceDoc . as < JsonObject > ( ) ;  
			
		
	
		
			
				
					            DynamicJsonDocument  doc ( 384 ) ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                 for ( uint8_t  i  =  0 ;  i  <  rec - > length ;  i + + )  {  
			
		
	
		
			
				
					            for   ( uint8_t  i  =  0 ;  i  <  rec - > length ;  i + + )  {  
			
		
	
		
			
				
					                if  ( rec - > assign [ i ] . ch  = =  CH0 )  {  
			
		
	
		
			
				
					                    snprintf ( name ,  32 ,  " %s %s " ,  iv - > name ,  iv - > getFieldName ( i ,  rec ) ) ;  
			
		
	
		
			
				
					                }  else  {  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -650,8 +671,8 @@ void app::sendMqttDiscoveryConfig(void) { 
			
		
	
		
			
				
					                snprintf ( stateTopic ,  64 ,  " %s/%s/ch%d/%s " ,  mConfig . mqtt . topic ,  iv - > name ,  rec - > assign [ i ] . ch ,  iv - > getFieldName ( i ,  rec ) ) ;  
			
		
	
		
			
				
					                snprintf ( discoveryTopic ,  64 ,  " %s/sensor/%s/ch%d_%s/config " ,  MQTT_DISCOVERY_PREFIX ,  iv - > name ,  rec - > assign [ i ] . ch ,  iv - > getFieldName ( i ,  rec ) ) ;  
			
		
	
		
			
				
					                snprintf ( uniq_id ,  32 ,  " ch%d_%s " ,  rec - > assign [ i ] . ch ,  iv - > getFieldName ( i ,  rec ) ) ;  
			
		
	
		
			
				
					                     const  char *   devCls  =  getFieldDeviceClass ( rec - > assign [ i ] . fieldId ) ;  
			
		
	
		
			
				
					                     const  char *   stateCls  =  getFieldStateClass ( rec - > assign [ i ] . fieldId ) ;  
			
		
	
		
			
				
					                const  char   * devCls  =  getFieldDeviceClass ( rec - > assign [ i ] . fieldId ) ;  
			
		
	
		
			
				
					                const  char   * stateCls  =  getFieldStateClass ( rec - > assign [ i ] . fieldId ) ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                doc [ " name " ]  =  name ;  
			
		
	
		
			
				
					                doc [ " stat_t " ]  =  stateTopic ;  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -666,7 +687,7 @@ void app::sendMqttDiscoveryConfig(void) { 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					                serializeJson ( doc ,  buffer ) ;  
			
		
	
		
			
				
					                mMqtt . sendMsg2 ( discoveryTopic ,  buffer ,  true ) ;  
			
		
	
		
			
				
					                     //DPRINTLN(DBG_INFO, F("mqtt sent"));
  
			
		
	
		
			
				
					                //  DPRINTLN(DBG_INFO, F("mqtt sent"));
  
			
		
	
		
			
				
					                doc . clear ( ) ;  
			
		
	
		
			
				
					            }  
			
		
	
		
			
				
					
 
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -679,29 +700,26 @@ void app::sendMqttDiscoveryConfig(void) { 
			
		
	
		
			
				
					    }  
			
		
	
		
			
				
					}  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					//-----------------------------------------------------------------------------
  
			
		
	
		
			
				
					const  char *   app : : getFieldDeviceClass ( uint8_t  fieldId )  {  
			
		
	
		
			
				
					const  char   * app : : getFieldDeviceClass ( uint8_t  fieldId )  {  
			
		
	
		
			
				
					    uint8_t  pos  =  0 ;  
			
		
	
		
			
				
					    for ( ;  pos  <  DEVICE_CLS_ASSIGN_LIST_LEN ;  pos + + )  {  
			
		
	
		
			
				
					        if ( deviceFieldAssignment [ pos ] . fieldId  = =  fieldId )  
			
		
	
		
			
				
					    for   ( ;  pos  <  DEVICE_CLS_ASSIGN_LIST_LEN ;  pos + + )  {  
			
		
	
		
			
				
					        if   ( deviceFieldAssignment [ pos ] . fieldId  = =  fieldId )  
			
		
	
		
			
				
					            break ;  
			
		
	
		
			
				
					    }  
			
		
	
		
			
				
					    return  ( pos  > =  DEVICE_CLS_ASSIGN_LIST_LEN )  ?  NULL  :  deviceClasses [ deviceFieldAssignment [ pos ] . deviceClsId ] ;  
			
		
	
		
			
				
					}  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					//-----------------------------------------------------------------------------
  
			
		
	
		
			
				
					const  char *   app : : getFieldStateClass ( uint8_t  fieldId )  {  
			
		
	
		
			
				
					const  char   * app : : getFieldStateClass ( uint8_t  fieldId )  {  
			
		
	
		
			
				
					    uint8_t  pos  =  0 ;  
			
		
	
		
			
				
					    for ( ;  pos  <  DEVICE_CLS_ASSIGN_LIST_LEN ;  pos + + )  {  
			
		
	
		
			
				
					        if ( deviceFieldAssignment [ pos ] . fieldId  = =  fieldId )  
			
		
	
		
			
				
					    for   ( ;  pos  <  DEVICE_CLS_ASSIGN_LIST_LEN ;  pos + + )  {  
			
		
	
		
			
				
					        if   ( deviceFieldAssignment [ pos ] . fieldId  = =  fieldId )  
			
		
	
		
			
				
					            break ;  
			
		
	
		
			
				
					    }  
			
		
	
		
			
				
					    return  ( pos  > =  DEVICE_CLS_ASSIGN_LIST_LEN )  ?  NULL  :  stateClasses [ deviceFieldAssignment [ pos ] . stateClsId ] ;  
			
		
	
		
			
				
					}  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					//-----------------------------------------------------------------------------
  
			
		
	
		
			
				
					void  app : : resetSystem ( void )  {  
			
		
	
		
			
				
					    mUptimeSecs  =  0 ;  
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -733,13 +751,11 @@ void app::resetSystem(void) { 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    mShowRebootRequest  =  false ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    memset ( mPayload ,  0 ,  ( MAX_NUM_INVERTERS  *  sizeof ( invPayload_t ) ) ) ;  
			
		
	
		
			
				
					    memset ( & mStat ,  0 ,  sizeof ( statistics_t ) ) ;  
			
		
	
		
			
				
					    mLastPacketId  =  0x00 ;  
			
		
	
		
			
				
					}  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					//-----------------------------------------------------------------------------
  
			
		
	
		
			
				
					void  app : : loadDefaultConfig ( void )  {  
			
		
	
		
			
				
					    memset ( & mSysConfig ,  0 ,  sizeof ( sysConfig_t ) ) ;  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -752,7 +768,6 @@ void app::loadDefaultConfig(void) { 
			
		
	
		
			
				
					    snprintf ( mSysConfig . stationSsid ,  SSID_LEN ,  " %s " ,  FB_WIFI_SSID ) ;  
			
		
	
		
			
				
					    snprintf ( mSysConfig . stationPwd ,  PWD_LEN ,  " %s " ,  FB_WIFI_PWD ) ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    // nrf24
  
			
		
	
		
			
				
					    mConfig . sendInterval  =  SEND_INTERVAL ;  
			
		
	
		
			
				
					    mConfig . maxRetransPerPyld  =  DEF_MAX_RETRANS_PER_PYLD ;  
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -786,15 +801,14 @@ void app::loadDefaultConfig(void) { 
			
		
	
		
			
				
					    mConfig . disclaimer  =  false ;  
			
		
	
		
			
				
					}  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					//-----------------------------------------------------------------------------
  
			
		
	
		
			
				
					void  app : : loadEEpconfig ( void )  {  
			
		
	
		
			
				
					    DPRINTLN ( DBG_VERBOSE ,  F ( " app::loadEEpconfig " ) ) ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    if ( mWifiSettingsValid )  
			
		
	
		
			
				
					        mEep - > read ( ADDR_CFG_SYS ,  ( uint8_t * )   & mSysConfig ,  CFG_SYS_LEN ) ;  
			
		
	
		
			
				
					    if ( mSettingsValid )  {  
			
		
	
		
			
				
					        mEep - > read ( ADDR_CFG ,  ( uint8_t * )   & mConfig ,  CFG_LEN ) ;  
			
		
	
		
			
				
					    if   ( mWifiSettingsValid )  
			
		
	
		
			
				
					        mEep - > read ( ADDR_CFG_SYS ,  ( uint8_t   * ) & mSysConfig ,  CFG_SYS_LEN ) ;  
			
		
	
		
			
				
					    if   ( mSettingsValid )  {  
			
		
	
		
			
				
					        mEep - > read ( ADDR_CFG ,  ( uint8_t   * ) & mConfig ,  CFG_LEN ) ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					        mSendTicker  =  mConfig . sendInterval ;  
			
		
	
		
			
				
					        mSerialTicker  =  0 ;  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -804,14 +818,14 @@ void app::loadEEpconfig(void) { 
			
		
	
		
			
				
					        char  name [ MAX_NAME_LENGTH  +  1 ]  =  { 0 } ;  
			
		
	
		
			
				
					        uint16_t  modPwr [ 4 ] ;  
			
		
	
		
			
				
					        Inverter < >  * iv ;  
			
		
	
		
			
				
					        for ( uint8_t  i  =  0 ;  i  <  MAX_NUM_INVERTERS ;  i   + + )  {  
			
		
	
		
			
				
					        for   ( uint8_t  i  =  0 ;  i  <  MAX_NUM_INVERTERS ;  i + + )  {  
			
		
	
		
			
				
					            mEep - > read ( ADDR_INV_ADDR  +  ( i  *  8 ) ,  & invSerial ) ;  
			
		
	
		
			
				
					            mEep - > read ( ADDR_INV_NAME  +  ( i  *  MAX_NAME_LENGTH ) ,  name ,  MAX_NAME_LENGTH ) ;  
			
		
	
		
			
				
					            mEep - > read ( ADDR_INV_CH_PWR  +  ( i  *  2  *  4 ) ,  modPwr ,  4 ) ;  
			
		
	
		
			
				
					            if ( 0ULL  ! =  invSerial )  {  
			
		
	
		
			
				
					            if   ( 0ULL  ! =  invSerial )  {  
			
		
	
		
			
				
					                iv  =  mSys - > addInverter ( name ,  invSerial ,  modPwr ) ;  
			
		
	
		
			
				
					                if ( NULL  ! =  iv )  {  // will run once on every dtu boot
  
			
		
	
		
			
				
					                    for ( uint8_t  j  =  0 ;  j  <  4 ;  j + + )  {  
			
		
	
		
			
				
					                if   ( NULL  ! =  iv )  {    // will run once on every dtu boot
  
			
		
	
		
			
				
					                    for   ( uint8_t  j  =  0 ;  j  <  4 ;  j + + )  {  
			
		
	
		
			
				
					                        mEep - > read ( ADDR_INV_CH_NAME  +  ( i  *  4  *  MAX_NAME_LENGTH )  +  j  *  MAX_NAME_LENGTH ,  iv - > chName [ j ] ,  MAX_NAME_LENGTH ) ;  
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					                }  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -821,29 +835,28 @@ void app::loadEEpconfig(void) { 
			
		
	
		
			
				
					            }  
			
		
	
		
			
				
					        }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					        for ( uint8_t  i  =  0 ;  i  <  MAX_NUM_INVERTERS ;  i + + )  {  
			
		
	
		
			
				
					        for   ( uint8_t  i  =  0 ;  i  <  MAX_NUM_INVERTERS ;  i + + )  {  
			
		
	
		
			
				
					            iv  =  mSys - > getInverterByPos ( i ,  false ) ;  
			
		
	
		
			
				
					            if ( NULL  ! =  iv )  
			
		
	
		
			
				
					            if   ( NULL  ! =  iv )  
			
		
	
		
			
				
					                resetPayload ( iv ) ;  
			
		
	
		
			
				
					        }  
			
		
	
		
			
				
					    }  
			
		
	
		
			
				
					}  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					//-----------------------------------------------------------------------------
  
			
		
	
		
			
				
					void  app : : saveValues ( void )  {  
			
		
	
		
			
				
					    DPRINTLN ( DBG_VERBOSE ,  F ( " app::saveValues " ) ) ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    mEep - > write ( ADDR_CFG_SYS ,  ( uint8_t * ) & mSysConfig ,  CFG_SYS_LEN ) ;  
			
		
	
		
			
				
					    mEep - > write ( ADDR_CFG ,  ( uint8_t * ) & mConfig ,  CFG_LEN ) ;  
			
		
	
		
			
				
					    mEep - > write ( ADDR_CFG_SYS ,  ( uint8_t   * ) & mSysConfig ,  CFG_SYS_LEN ) ;  
			
		
	
		
			
				
					    mEep - > write ( ADDR_CFG ,  ( uint8_t   * ) & mConfig ,  CFG_LEN ) ;  
			
		
	
		
			
				
					    Inverter < >  * iv ;  
			
		
	
		
			
				
					    for ( uint8_t  i  =  0 ;  i  <  MAX_NUM_INVERTERS ;  i   + + )  {  
			
		
	
		
			
				
					    for   ( uint8_t  i  =  0 ;  i  <  MAX_NUM_INVERTERS ;  i + + )  {  
			
		
	
		
			
				
					        iv  =  mSys - > getInverterByPos ( i ,  false ) ;  
			
		
	
		
			
				
					        mEep - > write ( ADDR_INV_ADDR  +  ( i  *  8 ) ,  iv - > serial . u64 ) ;  
			
		
	
		
			
				
					        mEep - > write ( ADDR_INV_NAME  +  ( i  *  MAX_NAME_LENGTH ) ,  iv - > name ,  MAX_NAME_LENGTH ) ;  
			
		
	
		
			
				
					        // max channel power / name
  
			
		
	
		
			
				
					        for ( uint8_t  j  =  0 ;  j  <  4 ;  j + + )  {  
			
		
	
		
			
				
					            mEep - > write ( ADDR_INV_CH_PWR  +  ( i  *  2  *  4 )  +  ( j * 2 ) ,  iv - > chMaxPwr [ j ] ) ;  
			
		
	
		
			
				
					        for   ( uint8_t  j  =  0 ;  j  <  4 ;  j + + )  {  
			
		
	
		
			
				
					            mEep - > write ( ADDR_INV_CH_PWR  +  ( i  *  2  *  4 )  +  ( j   *   2 ) ,  iv - > chMaxPwr [ j ] ) ;  
			
		
	
		
			
				
					            mEep - > write ( ADDR_INV_CH_NAME  +  ( i  *  4  *  MAX_NAME_LENGTH )  +  j  *  MAX_NAME_LENGTH ,  iv - > chName [ j ] ,  MAX_NAME_LENGTH ) ;  
			
		
	
		
			
				
					        }  
			
		
	
		
			
				
					    }  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -854,50 +867,33 @@ void app::saveValues(void) { 
			
		
	
		
			
				
					    mLatestSunTimestamp  =  0 ;  
			
		
	
		
			
				
					}  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					//-----------------------------------------------------------------------------
  
			
		
	
		
			
				
					void  app : : setupMqtt ( void )  {  
			
		
	
		
			
				
					    if ( mSettingsValid )  {  
			
		
	
		
			
				
					        if ( mConfig . mqtt . broker [ 0 ]  >  0 )  {  
			
		
	
		
			
				
					    if   ( mSettingsValid )  {  
			
		
	
		
			
				
					        if   ( mConfig . mqtt . broker [ 0 ]  >  0 )  {  
			
		
	
		
			
				
					            mMqttActive  =  true ;  
			
		
	
		
			
				
					            if ( mMqttInterval  <  MIN_MQTT_INTERVAL )  
			
		
	
		
			
				
					                mMqttInterval  =  MIN_MQTT_INTERVAL ;  
			
		
	
		
			
				
					        }  
			
		
	
		
			
				
					        else  
			
		
	
		
			
				
					            if  ( mMqttInterval  <  MIN_MQTT_INTERVAL )  mMqttInterval  =  MIN_MQTT_INTERVAL ;  
			
		
	
		
			
				
					        }  else  {  
			
		
	
		
			
				
					            mMqttInterval  =  0xffff ;  
			
		
	
		
			
				
					        }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					        mMqttTicker  =  0 ;  
			
		
	
		
			
				
					        mMqtt . setup ( & mConfig . mqtt ,  mSysConfig . deviceName ) ;  
			
		
	
		
			
				
					        mMqtt . setCallback ( std : : bind ( & app : : cbMqtt ,  this ,  std : : placeholders : : _1 ,  std : : placeholders : : _2 ,  std : : placeholders : : _3 ) ) ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					        if ( mMqttActive )  {  
			
		
	
		
			
				
					        if  ( mMqttActive )  {  
			
		
	
		
			
				
					            mMqtt . sendMsg ( " version " ,  mVersion ) ;  
			
		
	
		
			
				
					            if ( mMqtt . isConnected ( ) )  {  
			
		
	
		
			
				
					            if   ( mMqtt . isConnected ( ) )  {  
			
		
	
		
			
				
					                mMqtt . sendMsg ( " device " ,  mSysConfig . deviceName ) ;  
			
		
	
		
			
				
					                mMqtt . sendMsg ( " uptime " ,  " 0 " ) ;  
			
		
	
		
			
				
					            }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					            /*char topic[30];
  
			
		
	
		
			
				
					            for ( uint8_t  i  =  0 ;  i  <  MAX_NUM_INVERTERS ;  i  + + )  {  
			
		
	
		
			
				
					                iv  =  mSys - > getInverterByPos ( i ) ;  
			
		
	
		
			
				
					                if ( NULL  ! =  iv )  {  
			
		
	
		
			
				
					                    for ( uint8_t  i  =  0 ;  i  <  4 ;  i + + )  {  
			
		
	
		
			
				
					                        if ( 0  ! =  iv - > chName [ i ] [ 0 ] )  {  
			
		
	
		
			
				
					                            snprintf ( topic ,  30 ,  " %s/ch%d/%s " ,  iv - > name ,  i + 1 ,  " name " ) ;  
			
		
	
		
			
				
					                            mMqtt . sendMsg ( topic ,  iv - > chName [ i ] ) ;  
			
		
	
		
			
				
					                            yield ( ) ;  
			
		
	
		
			
				
					                        }  
			
		
	
		
			
				
					                    }  
			
		
	
		
			
				
					                }  
			
		
	
		
			
				
					            } */  
			
		
	
		
			
				
					        }  
			
		
	
		
			
				
					    }  
			
		
	
		
			
				
					}  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					//-----------------------------------------------------------------------------
  
			
		
	
		
			
				
					void  app : : resetPayload ( Inverter < > *   iv )  {  
			
		
	
		
			
				
					void  app : : resetPayload ( Inverter < >  * iv )  {  
			
		
	
		
			
				
					    DPRINTLN ( DBG_INFO ,  " resetPayload: id:  "  +  String ( iv - > id ) ) ;  
			
		
	
		
			
				
					    memset ( mPayload [ iv - > id ] . len ,  0 ,  MAX_PAYLOAD_ENTRIES ) ;  
			
		
	
		
			
				
					    mPayload [ iv - > id ] . txCmd  =  0 ;