|  | @ -34,13 +34,6 @@ struct alarm_t { | 
			
		
	
		
		
			
				
					|  |  |     alarm_t(uint16_t c, uint32_t s, uint32_t e) : code(c), start(s), end(e) {} |  |  |     alarm_t(uint16_t c, uint32_t s, uint32_t e) : code(c), start(s), end(e) {} | 
			
		
	
		
		
			
				
					|  |  | }; |  |  | }; | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  | typedef struct { |  |  |  | 
			
		
	
		
		
			
				
					|  |  |     bool running; |  |  |  | 
			
		
	
		
		
			
				
					|  |  |     uint8_t lastIvId; |  |  |  | 
			
		
	
		
		
			
				
					|  |  |     uint8_t sub; |  |  |  | 
			
		
	
		
		
			
				
					|  |  |     uint8_t foundIvCnt; |  |  |  | 
			
		
	
		
		
			
				
					|  |  | } discovery_t; |  |  |  | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  |  | 
			
		
	
		
		
			
				
					|  |  | template<class HMSYSTEM> |  |  | template<class HMSYSTEM> | 
			
		
	
		
		
			
				
					|  |  | class PubMqtt { |  |  | class PubMqtt { | 
			
		
	
		
		
			
				
					|  |  |     public: |  |  |     public: | 
			
		
	
	
		
		
			
				
					|  | @ -64,6 +57,7 @@ class PubMqtt { | 
			
		
	
		
		
			
				
					|  |  |             mIntervalTimeout = 1; |  |  |             mIntervalTimeout = 1; | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |             mDiscovery.running = false; |  |  |             mDiscovery.running = false; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             mSendIvData.running = false; | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |             snprintf(mLwtTopic, MQTT_TOPIC_LEN + 5, "%s/mqtt", mCfgMqtt->topic); |  |  |             snprintf(mLwtTopic, MQTT_TOPIC_LEN + 5, "%s/mqtt", mCfgMqtt->topic); | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
	
		
		
			
				
					|  | @ -93,6 +87,11 @@ class PubMqtt { | 
			
		
	
		
		
			
				
					|  |  |             yield(); |  |  |             yield(); | 
			
		
	
		
		
			
				
					|  |  |             #endif |  |  |             #endif | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             if(mSendIvData.running) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |                 sendIvDataLoop(); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |                 return; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             } | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |             if(mDiscovery.running) |  |  |             if(mDiscovery.running) | 
			
		
	
		
		
			
				
					|  |  |                 discoveryConfigLoop(); |  |  |                 discoveryConfigLoop(); | 
			
		
	
		
		
			
				
					|  |  |         } |  |  |         } | 
			
		
	
	
		
		
			
				
					|  | @ -107,13 +106,14 @@ class PubMqtt { | 
			
		
	
		
		
			
				
					|  |  |                 return; // next try in a second
 |  |  |                 return; // next try in a second
 | 
			
		
	
		
		
			
				
					|  |  |             } |  |  |             } | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |             if(0 == mCfgMqtt->interval) // no fixed interval, publish once new data were received (from inverter)
 |  |  |             if(0 == mCfgMqtt->interval) { // no fixed interval, publish once new data were received (from inverter)
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |                 sendIvData(); |  |  |                 sendIvDataStart(); | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					|  |  |  |  |  |             } | 
			
		
	
		
		
			
				
					|  |  |             else { // send mqtt data in a fixed interval
 |  |  |             else { // send mqtt data in a fixed interval
 | 
			
		
	
		
		
			
				
					|  |  |                 if(mIntervalTimeout == 0) { |  |  |                 if(mIntervalTimeout == 0) { | 
			
		
	
		
		
			
				
					|  |  |                     mIntervalTimeout = mCfgMqtt->interval; |  |  |                     mIntervalTimeout = mCfgMqtt->interval; | 
			
		
	
		
		
			
				
					|  |  |                     mSendList.push(RealTimeRunData_Debug); |  |  |                     mSendList.push(RealTimeRunData_Debug); | 
			
		
	
		
		
			
				
					
					|  |  |                     sendIvData(); |  |  |                     sendIvDataStart(); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  |                 } |  |  |                 } | 
			
		
	
		
		
			
				
					|  |  |             } |  |  |             } | 
			
		
	
		
		
			
				
					|  |  |         } |  |  |         } | 
			
		
	
	
		
		
			
				
					|  | @ -554,55 +554,65 @@ class PubMqtt { | 
			
		
	
		
		
			
				
					|  |  |             } |  |  |             } | 
			
		
	
		
		
			
				
					|  |  |         } |  |  |         } | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |         void sendIvData() { |  |  |         void sendIvDataStart() { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  |  |  |  |             mSendIvData.RTRDataHasBeenSent = false; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             memset(mSendIvData.total, 0, sizeof(float) * 4); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             for (uint8_t id = 0; id < mSys->getNumInverters(); id++) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |                 Inverter<> *iv = mSys->getInverterByPos(id); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |                 if (NULL != iv) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |                     if (iv->config->enabled) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |                         mSendIvData.lastIvId = id; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |                         mSendIvData.running = true; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |                         mSendIvData.lastIvReached = false; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |                         mSendIvData.sendTotals = false; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |                         break; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |                     } | 
			
		
	
		
		
			
				
					|  |  |  |  |  |                 } | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             } | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         } | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         void sendIvDataLoop(void) { | 
			
		
	
		
		
			
				
					|  |  |             bool anyAvail = processIvStatus(); |  |  |             bool anyAvail = processIvStatus(); | 
			
		
	
		
		
			
				
					|  |  |             if (mLastAnyAvail != anyAvail) |  |  |             if (mLastAnyAvail != anyAvail) | 
			
		
	
		
		
			
				
					
					|  |  |                 mSendList.push(RealTimeRunData_Debug);  // makes shure that total values are calculated
 |  |  |                 mSendList.push(RealTimeRunData_Debug);  // makes sure that total values are calculated
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |             if(mSendList.empty()) |  |  |             if(mSendList.empty()) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  |  |  |  |                 mSendIvData.running = false; | 
			
		
	
		
		
			
				
					|  |  |                 return; |  |  |                 return; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             } | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |             float total[4]; |  |  |  | 
			
		
	
		
		
			
				
					|  |  |             bool RTRDataHasBeenSent = false; |  |  |  | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |             while(!mSendList.empty()) { |  |  |             //while(!mSendList.empty()) {
 | 
			
				
				
			
		
	
		
		
			
				
					|  |  |                 memset(total, 0, sizeof(float) * 4); |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					|  |  |                 uint8_t curInfoCmd = mSendList.front(); |  |  |                 uint8_t curInfoCmd = mSendList.front(); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |                 if ((curInfoCmd != RealTimeRunData_Debug) || !mSendIvData.RTRDataHasBeenSent) { // send RTR Data only once
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |                     mSendIvData.sendTotals = (curInfoCmd == RealTimeRunData_Debug); | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |                 if ((curInfoCmd != RealTimeRunData_Debug) || !RTRDataHasBeenSent) { // send RTR Data only once
 |  |  |                     if(!mSendIvData.lastIvReached) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |                     bool sendTotals = (curInfoCmd == RealTimeRunData_Debug); |  |  |                         Inverter<> *iv = mSys->getInverterByPos(mSendIvData.lastIvId); | 
			
				
				
			
		
	
		
		
			
				
					|  |  | 
 |  |  |  | 
			
		
	
		
		
			
				
					|  |  |                     for (uint8_t id = 0; id < mSys->getNumInverters(); id++) { |  |  |  | 
			
		
	
		
		
			
				
					|  |  |                         Inverter<> *iv = mSys->getInverterByPos(id); |  |  |  | 
			
		
	
		
		
			
				
					|  |  |                         if (NULL == iv) |  |  |  | 
			
		
	
		
		
			
				
					|  |  |                             continue; // skip to next inverter
 |  |  |  | 
			
		
	
		
		
			
				
					|  |  |                         if (!iv->config->enabled) |  |  |  | 
			
		
	
		
		
			
				
					|  |  |                             continue; // skip to next inverter
 |  |  |  | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
			
				
					|  |  |                         // send RTR Data only if status is available
 |  |  |                         // send RTR Data only if status is available
 | 
			
		
	
		
		
			
				
					
					|  |  |                         if ((curInfoCmd != RealTimeRunData_Debug) || (MQTT_STATUS_NOT_AVAIL_NOT_PROD != mLastIvState[id])) |  |  |                         if ((curInfoCmd != RealTimeRunData_Debug) || (MQTT_STATUS_NOT_AVAIL_NOT_PROD != mLastIvState[mSendIvData.lastIvId])) | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  |                             sendData(iv, curInfoCmd); |  |  |                             sendData(iv, curInfoCmd); | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |                         // calculate total values for RealTimeRunData_Debug
 |  |  |                         // calculate total values for RealTimeRunData_Debug
 | 
			
		
	
		
		
			
				
					
					|  |  |                         if (sendTotals) { |  |  |                         if (mSendIvData.sendTotals) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  |                             record_t<> *rec = iv->getRecordStruct(curInfoCmd); |  |  |                             record_t<> *rec = iv->getRecordStruct(curInfoCmd); | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |                             sendTotals &= (iv->getLastTs(rec) > 0); |  |  |                             mSendIvData.sendTotals &= (iv->getLastTs(rec) > 0); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |                             if (sendTotals) { |  |  |                             if (mSendIvData.sendTotals) { | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					|  |  |                                 for (uint8_t i = 0; i < rec->length; i++) { |  |  |                                 for (uint8_t i = 0; i < rec->length; i++) { | 
			
		
	
		
		
			
				
					|  |  |                                     if (CH0 == rec->assign[i].ch) { |  |  |                                     if (CH0 == rec->assign[i].ch) { | 
			
		
	
		
		
			
				
					|  |  |                                         switch (rec->assign[i].fieldId) { |  |  |                                         switch (rec->assign[i].fieldId) { | 
			
		
	
		
		
			
				
					|  |  |                                             case FLD_PAC: |  |  |                                             case FLD_PAC: | 
			
		
	
		
		
			
				
					
					|  |  |                                                 total[0] += iv->getValue(i, rec); |  |  |                                                 mSendIvData.total[0] += iv->getValue(i, rec); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  |                                                 break; |  |  |                                                 break; | 
			
		
	
		
		
			
				
					|  |  |                                             case FLD_YT: |  |  |                                             case FLD_YT: | 
			
		
	
		
		
			
				
					
					|  |  |                                                 total[1] += iv->getValue(i, rec); |  |  |                                                 mSendIvData.total[1] += iv->getValue(i, rec); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  |                                                 break; |  |  |                                                 break; | 
			
		
	
		
		
			
				
					|  |  |                                             case FLD_YD: |  |  |                                             case FLD_YD: | 
			
		
	
		
		
			
				
					
					|  |  |                                                 total[2] += iv->getValue(i, rec); |  |  |                                                 mSendIvData.total[2] += iv->getValue(i, rec); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  |                                                 break; |  |  |                                                 break; | 
			
		
	
		
		
			
				
					|  |  |                                             case FLD_PDC: |  |  |                                             case FLD_PDC: | 
			
		
	
		
		
			
				
					
					|  |  |                                                 total[3] += iv->getValue(i, rec); |  |  |                                                 mSendIvData.total[3] += iv->getValue(i, rec); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  |                                                 break; |  |  |                                                 break; | 
			
		
	
		
		
			
				
					|  |  |                                         } |  |  |                                         } | 
			
		
	
		
		
			
				
					|  |  |                                     } |  |  |                                     } | 
			
		
	
	
		
		
			
				
					|  | @ -610,9 +620,21 @@ class PubMqtt { | 
			
		
	
		
		
			
				
					|  |  |                             } |  |  |                             } | 
			
		
	
		
		
			
				
					|  |  |                         } |  |  |                         } | 
			
		
	
		
		
			
				
					|  |  |                         yield(); |  |  |                         yield(); | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |                         // get next inverter
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |                         for (uint8_t id = mSendIvData.lastIvId; id < mSys->getNumInverters(); id++) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |                             Inverter<> *iv = mSys->getInverterByPos(id); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |                             if (NULL != iv) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |                                 if (iv->config->enabled) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |                                     mSendIvData.lastIvId = id; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |                                     return; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |                                 } | 
			
		
	
		
		
			
				
					|  |  |  |  |  |                             } | 
			
		
	
		
		
			
				
					|  |  |  |  |  |                         } | 
			
		
	
		
		
			
				
					|  |  |  |  |  |                         mSendIvData.lastIvReached = true; | 
			
		
	
		
		
			
				
					|  |  |                     } |  |  |                     } | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |                     if (sendTotals) { |  |  |                     if (mSendIvData.sendTotals) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  |                         uint8_t fieldId; |  |  |                         uint8_t fieldId; | 
			
		
	
		
		
			
				
					|  |  |                         for (uint8_t i = 0; i < 4; i++) { |  |  |                         for (uint8_t i = 0; i < 4; i++) { | 
			
		
	
		
		
			
				
					|  |  |                             bool retained = true; |  |  |                             bool retained = true; | 
			
		
	
	
		
		
			
				
					|  | @ -634,20 +656,36 @@ class PubMqtt { | 
			
		
	
		
		
			
				
					|  |  |                                     break; |  |  |                                     break; | 
			
		
	
		
		
			
				
					|  |  |                             } |  |  |                             } | 
			
		
	
		
		
			
				
					|  |  |                             snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "total/%s", fields[fieldId]); |  |  |                             snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "total/%s", fields[fieldId]); | 
			
		
	
		
		
			
				
					
					|  |  |                             snprintf(mVal, 40, "%g", ah::round3(total[i])); |  |  |                             snprintf(mVal, 40, "%g", ah::round3(mSendIvData.total[i])); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  |                             publish(mSubTopic, mVal, retained); |  |  |                             publish(mSubTopic, mVal, retained); | 
			
		
	
		
		
			
				
					|  |  |                         } |  |  |                         } | 
			
		
	
		
		
			
				
					
					|  |  |                         RTRDataHasBeenSent = true; |  |  |                         mSendIvData.RTRDataHasBeenSent = true; | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  |                         yield(); |  |  |                         yield(); | 
			
		
	
		
		
			
				
					|  |  |                     } |  |  |                     } | 
			
		
	
		
		
			
				
					|  |  |                 } |  |  |                 } | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |                 mSendList.pop(); // remove from list once all inverters were processed
 |  |  |                 mSendList.pop(); // remove from list once all inverters were processed
 | 
			
		
	
		
		
			
				
					
					|  |  |             } |  |  |             //} // end while
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |             mLastAnyAvail = anyAvail; |  |  |             mLastAnyAvail = anyAvail; | 
			
		
	
		
		
			
				
					|  |  |         } |  |  |         } | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         typedef struct { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             bool running; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             uint8_t lastIvId; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             bool lastIvReached; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             bool sendTotals; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             float total[4]; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             bool RTRDataHasBeenSent; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         } publish_t; | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         typedef struct { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             bool running; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             uint8_t lastIvId; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             uint8_t sub; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             uint8_t foundIvCnt; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         } discovery_t; | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |         espMqttClient mClient; |  |  |         espMqttClient mClient; | 
			
		
	
		
		
			
				
					|  |  |         cfgMqtt_t *mCfgMqtt; |  |  |         cfgMqtt_t *mCfgMqtt; | 
			
		
	
		
		
			
				
					|  |  |         #if defined(ESP8266) |  |  |         #if defined(ESP8266) | 
			
		
	
	
		
		
			
				
					|  | @ -674,6 +712,7 @@ class PubMqtt { | 
			
		
	
		
		
			
				
					|  |  |         char mSubTopic[32 + MAX_NAME_LENGTH + 1]; |  |  |         char mSubTopic[32 + MAX_NAME_LENGTH + 1]; | 
			
		
	
		
		
			
				
					|  |  |         char mVal[40]; |  |  |         char mVal[40]; | 
			
		
	
		
		
			
				
					|  |  |         discovery_t mDiscovery; |  |  |         discovery_t mDiscovery; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         publish_t mSendIvData; | 
			
		
	
		
		
			
				
					|  |  | }; |  |  | }; | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  | #endif /*__PUB_MQTT_H__*/ |  |  | #endif /*__PUB_MQTT_H__*/ | 
			
		
	
	
		
		
			
				
					|  | 
 |