|  |  | @ -11,21 +11,23 @@ | 
			
		
	
		
			
				
					|  |  |  | #include "../utils/crc.h" | 
			
		
	
		
			
				
					|  |  |  | #include "Heuristic.h" | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | #define MI_TIMEOUT      250      // timeout for MI type requests
 | 
			
		
	
		
			
				
					|  |  |  | #define FRSTMSG_TIMEOUT 150      // how long to wait for first msg to be received
 | 
			
		
	
		
			
				
					|  |  |  | #define DEFAULT_TIMEOUT 500      // timeout for regular requests
 | 
			
		
	
		
			
				
					|  |  |  | #define SINGLEFR_TIMEOUT 65      // timeout for single frame requests
 | 
			
		
	
		
			
				
					|  |  |  | #define MAX_BUFFER      250 | 
			
		
	
		
			
				
					|  |  |  | #define MI_TIMEOUT          250 // timeout for MI type requests
 | 
			
		
	
		
			
				
					|  |  |  | #define FRSTMSG_TIMEOUT     150 // how long to wait for first msg to be received
 | 
			
		
	
		
			
				
					|  |  |  | #define DEFAULT_TIMEOUT     500 // timeout for regular requests
 | 
			
		
	
		
			
				
					|  |  |  | #define SINGLEFR_TIMEOUT     65 // timeout for single frame requests
 | 
			
		
	
		
			
				
					|  |  |  | #define WAIT_GAP_TIMEOUT    200 // timeout after no complete payload
 | 
			
		
	
		
			
				
					|  |  |  | #define MAX_BUFFER          250 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | typedef std::function<void(uint8_t, Inverter<> *)> payloadListenerType; | 
			
		
	
		
			
				
					|  |  |  | typedef std::function<void(Inverter<> *)> alarmListenerType; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | class Communication : public CommQueue<> { | 
			
		
	
		
			
				
					|  |  |  |     public: | 
			
		
	
		
			
				
					|  |  |  |         void setup(uint32_t *timestamp, bool *serialDebug, bool *privacyMode) { | 
			
		
	
		
			
				
					|  |  |  |         void setup(uint32_t *timestamp, bool *serialDebug, bool *privacyMode, bool *printWholeTrace) { | 
			
		
	
		
			
				
					|  |  |  |             mTimestamp = timestamp; | 
			
		
	
		
			
				
					|  |  |  |             mPrivacyMode = privacyMode; | 
			
		
	
		
			
				
					|  |  |  |             mSerialDebug = serialDebug; | 
			
		
	
		
			
				
					|  |  |  |             mPrintWholeTrace = printWholeTrace; | 
			
		
	
		
			
				
					|  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         void addImportant(Inverter<> *iv, uint8_t cmd, bool delOnPop = true) { | 
			
		
	
	
		
			
				
					|  |  | @ -47,7 +49,7 @@ class Communication : public CommQueue<> { | 
			
		
	
		
			
				
					|  |  |  |                     return; // empty
 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 uint16_t timeout     = (q->iv->ivGen == IV_MI) ? MI_TIMEOUT : ((q->iv->mGotFragment && q->iv->mGotLastMsg) || mIsResend) ? SINGLEFR_TIMEOUT : DEFAULT_TIMEOUT; | 
			
		
	
		
			
				
					|  |  |  |                 uint16_t timeout_min = (q->iv->ivGen == IV_MI) ? MI_TIMEOUT : ((q->iv->mGotFragment) ? SINGLEFR_TIMEOUT : FRSTMSG_TIMEOUT); | 
			
		
	
		
			
				
					|  |  |  |                 uint16_t timeout_min = (q->iv->ivGen == IV_MI) ? MI_TIMEOUT : ((q->iv->mGotFragment || mIsResend)) ? SINGLEFR_TIMEOUT : FRSTMSG_TIMEOUT; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                 switch(mState) { | 
			
		
	
		
			
				
					|  |  |  |                     case States::RESET: | 
			
		
	
	
		
			
				
					|  |  | @ -63,6 +65,7 @@ class Communication : public CommQueue<> { | 
			
		
	
		
			
				
					|  |  |  |                         mHeu.getTxCh(q->iv); | 
			
		
	
		
			
				
					|  |  |  |                         q->iv->mGotFragment = false; | 
			
		
	
		
			
				
					|  |  |  |                         q->iv->mGotLastMsg  = false; | 
			
		
	
		
			
				
					|  |  |  |                         mIsResend = false; | 
			
		
	
		
			
				
					|  |  |  |                         if(NULL == q->iv->radio) | 
			
		
	
		
			
				
					|  |  |  |                             cmdDone(true); // can't communicate while radio is not defined!
 | 
			
		
	
		
			
				
					|  |  |  |                         mState = States::START; | 
			
		
	
	
		
			
				
					|  |  | @ -97,7 +100,9 @@ class Communication : public CommQueue<> { | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                     case States::WAIT: | 
			
		
	
		
			
				
					|  |  |  |                         if(millis() > mWaitTimeout_min) { | 
			
		
	
		
			
				
					|  |  |  |                             if(q->iv->mGotFragment) { // nothing received yet?
 | 
			
		
	
		
			
				
					|  |  |  |                             if(mIsResend) { // we already have been through...
 | 
			
		
	
		
			
				
					|  |  |  |                                 mWaitTimeout = mWaitTimeout_min; | 
			
		
	
		
			
				
					|  |  |  |                             } else if(q->iv->mGotFragment) { // nothing received yet?
 | 
			
		
	
		
			
				
					|  |  |  |                                 if(q->iv->mGotLastMsg) { | 
			
		
	
		
			
				
					|  |  |  |                                     //mState = States::CHECK_FRAMES;
 | 
			
		
	
		
			
				
					|  |  |  |                                     mWaitTimeout = mWaitTimeout_min; | 
			
		
	
	
		
			
				
					|  |  | @ -123,8 +128,7 @@ class Communication : public CommQueue<> { | 
			
		
	
		
			
				
					|  |  |  |                         break; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                     case States::CHECK_FRAMES: { | 
			
		
	
		
			
				
					|  |  |  |                         if((!q->iv->radio->get() && !mIsResend) || ((q->iv->mGotFragment) && (0 == q->attempts))) { // radio buffer empty
 | 
			
		
	
		
			
				
					|  |  |  |                             //cmdDone();
 | 
			
		
	
		
			
				
					|  |  |  |                         if((!q->iv->radio->get() && !mIsResend) || (((q->iv->mGotFragment) || (mIsResend)) && (0 == q->attempts))) { // radio buffer empty or no more answers
 | 
			
		
	
		
			
				
					|  |  |  |                             if(*mSerialDebug) { | 
			
		
	
		
			
				
					|  |  |  |                                 DPRINT_IVID(DBG_INFO, q->iv->id); | 
			
		
	
		
			
				
					|  |  |  |                                 DBGPRINT(F("request timeout: ")); | 
			
		
	
	
		
			
				
					|  |  | @ -153,21 +157,26 @@ class Communication : public CommQueue<> { | 
			
		
	
		
			
				
					|  |  |  |                             if(p->millis < 100) | 
			
		
	
		
			
				
					|  |  |  |                                 DBGPRINT(F(" ")); | 
			
		
	
		
			
				
					|  |  |  |                             DBGPRINT(String(p->millis)); | 
			
		
	
		
			
				
					|  |  |  |                             DBGPRINT(F("ms ")); | 
			
		
	
		
			
				
					|  |  |  |                             DBGPRINT(F("ms | ")); | 
			
		
	
		
			
				
					|  |  |  |                             DBGPRINT(String(p->len)); | 
			
		
	
		
			
				
					|  |  |  |                             if((IV_HM == q->iv->ivGen) || (IV_MI == q->iv->ivGen)) { | 
			
		
	
		
			
				
					|  |  |  |                                 DBGPRINT(F(" CH")); | 
			
		
	
		
			
				
					|  |  |  |                                 if(3 == p->ch) | 
			
		
	
		
			
				
					|  |  |  |                                     DBGPRINT(F("0")); | 
			
		
	
		
			
				
					|  |  |  |                                 DBGPRINT(String(p->ch)); | 
			
		
	
		
			
				
					|  |  |  |                             } else { | 
			
		
	
		
			
				
					|  |  |  |                                 DBGPRINT(String(p->rssi)); | 
			
		
	
		
			
				
					|  |  |  |                                 DBGPRINT(F("dBm | ")); | 
			
		
	
		
			
				
					|  |  |  |                             } | 
			
		
	
		
			
				
					|  |  |  |                             if(*mPrintWholeTrace) { | 
			
		
	
		
			
				
					|  |  |  |                                 if(*mPrivacyMode) | 
			
		
	
		
			
				
					|  |  |  |                                     ah::dumpBuf(p->packet, p->len, 1, 8); | 
			
		
	
		
			
				
					|  |  |  |                                 else | 
			
		
	
		
			
				
					|  |  |  |                                     ah::dumpBuf(p->packet, p->len); | 
			
		
	
		
			
				
					|  |  |  |                             } else { | 
			
		
	
		
			
				
					|  |  |  |                                 DBGPRINT(F("frm ")); | 
			
		
	
		
			
				
					|  |  |  |                                 DBGHEXLN(p->packet[9]); | 
			
		
	
		
			
				
					|  |  |  |                             } | 
			
		
	
		
			
				
					|  |  |  |                             DBGPRINT(F(", ")); | 
			
		
	
		
			
				
					|  |  |  |                             DBGPRINT(String(p->rssi)); | 
			
		
	
		
			
				
					|  |  |  |                             DBGPRINT(F("dBm | ")); | 
			
		
	
		
			
				
					|  |  |  |                             if(*mPrivacyMode) | 
			
		
	
		
			
				
					|  |  |  |                                 ah::dumpBuf(p->packet, p->len, 1, 8); | 
			
		
	
		
			
				
					|  |  |  |                             else | 
			
		
	
		
			
				
					|  |  |  |                                 ah::dumpBuf(p->packet, p->len); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                             if(checkIvSerial(&p->packet[1], q->iv)) { | 
			
		
	
		
			
				
					|  |  |  |                                 if(!mHeu.getTestModeEnabled()) | 
			
		
	
	
		
			
				
					|  |  | @ -178,7 +187,7 @@ class Communication : public CommQueue<> { | 
			
		
	
		
			
				
					|  |  |  |                                     nextState = States::CHECK_PACKAGE; | 
			
		
	
		
			
				
					|  |  |  |                                 } else if (p->packet[0] == (TX_REQ_DEVCONTROL + ALL_FRAMES)) { // response from dev control command
 | 
			
		
	
		
			
				
					|  |  |  |                                     parseDevCtrl(p, q); | 
			
		
	
		
			
				
					|  |  |  |                                     cmdDone(true); // remove done request
 | 
			
		
	
		
			
				
					|  |  |  |                                     closeRequest(q->iv, true); | 
			
		
	
		
			
				
					|  |  |  |                                 } else if(IV_MI == q->iv->ivGen) { | 
			
		
	
		
			
				
					|  |  |  |                                     parseMiFrame(p, q); | 
			
		
	
		
			
				
					|  |  |  |                                 } | 
			
		
	
	
		
			
				
					|  |  | @ -198,19 +207,20 @@ class Communication : public CommQueue<> { | 
			
		
	
		
			
				
					|  |  |  |                             if(q->iv->ivGen != IV_MI) | 
			
		
	
		
			
				
					|  |  |  |                                 mState = nextState; | 
			
		
	
		
			
				
					|  |  |  |                             else { | 
			
		
	
		
			
				
					|  |  |  |                                 if(  q->iv->miMultiParts > 5 && | 
			
		
	
		
			
				
					|  |  |  |                                    ((q->cmd == 0x39) && (q->iv->type == INV_TYPE_4CH) || | 
			
		
	
		
			
				
					|  |  |  |                                     (q->cmd == MI_REQ_CH2) && (q->iv->type == INV_TYPE_2CH) || | 
			
		
	
		
			
				
					|  |  |  |                                     (q->cmd == MI_REQ_CH1) && (q->iv->type == INV_TYPE_1CH))) { | 
			
		
	
		
			
				
					|  |  |  |                                 if(q->iv->miMultiParts < 6) { | 
			
		
	
		
			
				
					|  |  |  |                                     nextState = States::WAIT; | 
			
		
	
		
			
				
					|  |  |  |                                 } else { | 
			
		
	
		
			
				
					|  |  |  |                                     if((q->cmd == 0x39)       && (q->iv->type == INV_TYPE_4CH) || | 
			
		
	
		
			
				
					|  |  |  |                                        (q->cmd == MI_REQ_CH2) && (q->iv->type == INV_TYPE_2CH) || | 
			
		
	
		
			
				
					|  |  |  |                                        (q->cmd == MI_REQ_CH1) && (q->iv->type == INV_TYPE_1CH)) { | 
			
		
	
		
			
				
					|  |  |  |                                         miComplete(q->iv); | 
			
		
	
		
			
				
					|  |  |  |                                         //closeRequest(q->iv, q->iv->miMultiParts > 5);
 | 
			
		
	
		
			
				
					|  |  |  |                                     } else if (q->iv->miMultiParts > 5) | 
			
		
	
		
			
				
					|  |  |  |                                         closeRequest(q->iv, true); | 
			
		
	
		
			
				
					|  |  |  |                                     else { | 
			
		
	
		
			
				
					|  |  |  |                                         nextState = States::WAIT; | 
			
		
	
		
			
				
					|  |  |  |                                     } | 
			
		
	
		
			
				
					|  |  |  |                                     closeRequest(q->iv, true); | 
			
		
	
		
			
				
					|  |  |  |                                 } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                             } | 
			
		
	
		
			
				
					|  |  |  |                         } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                         } | 
			
		
	
		
			
				
					|  |  |  |                         break; | 
			
		
	
	
		
			
				
					|  |  | @ -240,12 +250,14 @@ class Communication : public CommQueue<> { | 
			
		
	
		
			
				
					|  |  |  |                         if(framnr) { | 
			
		
	
		
			
				
					|  |  |  |                             setAttempt(); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |                             DPRINT_IVID(DBG_WARN, q->iv->id); | 
			
		
	
		
			
				
					|  |  |  |                             DBGPRINT(F("frame ")); | 
			
		
	
		
			
				
					|  |  |  |                             DBGPRINT(String(framnr)); | 
			
		
	
		
			
				
					|  |  |  |                             DBGPRINT(F(" missing: request retransmit (")); | 
			
		
	
		
			
				
					|  |  |  |                             DBGPRINT(String(q->attempts)); | 
			
		
	
		
			
				
					|  |  |  |                             DBGPRINTLN(F(" attempts left)")); | 
			
		
	
		
			
				
					|  |  |  |                             if(*mSerialDebug) { | 
			
		
	
		
			
				
					|  |  |  |                                 DPRINT_IVID(DBG_WARN, q->iv->id); | 
			
		
	
		
			
				
					|  |  |  |                                 DBGPRINT(F("frame ")); | 
			
		
	
		
			
				
					|  |  |  |                                 DBGPRINT(String(framnr)); | 
			
		
	
		
			
				
					|  |  |  |                                 DBGPRINT(F(" missing: request retransmit (")); | 
			
		
	
		
			
				
					|  |  |  |                                 DBGPRINT(String(q->attempts)); | 
			
		
	
		
			
				
					|  |  |  |                                 DBGPRINTLN(F(" attempts left)")); | 
			
		
	
		
			
				
					|  |  |  |                             } | 
			
		
	
		
			
				
					|  |  |  |                             sendRetransmit(q, framnr-1); | 
			
		
	
		
			
				
					|  |  |  |                             mIsResend = true; | 
			
		
	
		
			
				
					|  |  |  |                             mlastTO_min = timeout_min; | 
			
		
	
	
		
			
				
					|  |  | @ -448,7 +460,7 @@ class Communication : public CommQueue<> { | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     private: | 
			
		
	
		
			
				
					|  |  |  |         void closeRequest(Inverter<> *iv, bool succeeded = true, bool delCmd = true) { | 
			
		
	
		
			
				
					|  |  |  |             // ordering of lines is relevant for statistics
 | 
			
		
	
		
			
				
					|  |  |  |         // ordering of lines is relevant for statistics
 | 
			
		
	
		
			
				
					|  |  |  |             if(succeeded) { | 
			
		
	
		
			
				
					|  |  |  |                 mHeu.setGotAll(iv); | 
			
		
	
		
			
				
					|  |  |  |                 if(!mHeu.getTestModeEnabled()) | 
			
		
	
	
		
			
				
					|  |  | @ -461,11 +473,13 @@ class Communication : public CommQueue<> { | 
			
		
	
		
			
				
					|  |  |  |                 if(!mHeu.getTestModeEnabled()) | 
			
		
	
		
			
				
					|  |  |  |                     iv->radioStatistics.rxFailNoAnser++; // got nothing
 | 
			
		
	
		
			
				
					|  |  |  |                 mHeu.setGotNothing(iv); | 
			
		
	
		
			
				
					|  |  |  |                 mWaitTimeout = millis() + WAIT_GAP_TIMEOUT; | 
			
		
	
		
			
				
					|  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |             cmdDone(delCmd); | 
			
		
	
		
			
				
					|  |  |  |             iv->mGotFragment = false; | 
			
		
	
		
			
				
					|  |  |  |             iv->mGotLastMsg  = false; | 
			
		
	
		
			
				
					|  |  |  |             iv->miMultiParts = 0; | 
			
		
	
		
			
				
					|  |  |  |             mIsResend        = false; | 
			
		
	
		
			
				
					|  |  |  |             mFirstTry        = false; // for correct reset
 | 
			
		
	
		
			
				
					|  |  |  |             mState           = States::RESET; | 
			
		
	
		
			
				
					|  |  |  |         } | 
			
		
	
	
		
			
				
					|  |  | @ -788,7 +802,7 @@ class Communication : public CommQueue<> { | 
			
		
	
		
			
				
					|  |  |  |             // update status state-machine,
 | 
			
		
	
		
			
				
					|  |  |  |             if (ac_pow) | 
			
		
	
		
			
				
					|  |  |  |                 iv->isProducing(); | 
			
		
	
		
			
				
					|  |  |  |             closeRequest(iv, iv->miMultiParts > 5); | 
			
		
	
		
			
				
					|  |  |  |             //closeRequest(iv, iv->miMultiParts > 5);
 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |             //mHeu.setGotAll(iv);
 | 
			
		
	
		
			
				
					|  |  |  |             //cmdDone(true);
 | 
			
		
	
	
		
			
				
					|  |  | @ -812,7 +826,7 @@ class Communication : public CommQueue<> { | 
			
		
	
		
			
				
					|  |  |  |     private: | 
			
		
	
		
			
				
					|  |  |  |         States mState = States::RESET; | 
			
		
	
		
			
				
					|  |  |  |         uint32_t *mTimestamp; | 
			
		
	
		
			
				
					|  |  |  |         bool *mPrivacyMode, *mSerialDebug; | 
			
		
	
		
			
				
					|  |  |  |         bool *mPrivacyMode, *mSerialDebug, *mPrintWholeTrace; | 
			
		
	
		
			
				
					|  |  |  |         uint32_t mWaitTimeout     = 0; | 
			
		
	
		
			
				
					|  |  |  |         uint32_t mWaitTimeout_min = 0; | 
			
		
	
		
			
				
					|  |  |  |         std::array<frame_t, MAX_PAYLOAD_ENTRIES> mLocalBuf; | 
			
		
	
	
		
			
				
					|  |  | 
 |