diff --git a/src/defines.h b/src/defines.h index fe9acf95..21c583b0 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 8 -#define VERSION_PATCH 7 +#define VERSION_PATCH 0707 //------------------------------------- typedef struct { diff --git a/src/hm/CommQueue.h b/src/hm/CommQueue.h index 8d0bb0f8..9771393d 100644 --- a/src/hm/CommQueue.h +++ b/src/hm/CommQueue.h @@ -85,6 +85,10 @@ class CommQueue { mQueue[mRdPtr].attempts--; } + void incrAttempt(void) { + mQueue[mRdPtr].attempts++; + } + void inc(uint8_t *ptr) { if(++(*ptr) >= N) *ptr = 0; diff --git a/src/hm/Communication.h b/src/hm/Communication.h index a4eb43eb..f23fe416 100644 --- a/src/hm/Communication.h +++ b/src/hm/Communication.h @@ -11,9 +11,10 @@ #include "../utils/crc.h" #include "Heuristic.h" -#define MI_TIMEOUT 250 -#define DEFAULT_TIMEOUT 500 -#define SINGLEFR_TIMEOUT 60 +#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 60 // timeout for single frame requests #define MAX_BUFFER 250 typedef std::function *)> payloadListenerType; @@ -43,7 +44,8 @@ class Communication : public CommQueue<> { if(!valid) return; // empty - uint16_t timeout = q->iv->ivGen != IV_MI ? DEFAULT_TIMEOUT : MI_TIMEOUT; + uint16_t timeout = q->iv->ivGen != IV_MI ? (mGotFragment && q->iv->mGotLastMsg) ? SINGLEFR_TIMEOUT : DEFAULT_TIMEOUT : MI_TIMEOUT; + uint16_t timeout_min = q->iv->ivGen != IV_MI ? mGotFragment ? SINGLEFR_TIMEOUT : FRSTMSG_TIMEOUT : MI_TIMEOUT; bool testMode = false; switch(mState) { @@ -55,11 +57,13 @@ class Communication : public CommQueue<> { mLocalBuf[i].len = 0; } - mHeu.printStatus(q->iv); + if(q->iv->radio->isSerialDebug()) + mHeu.printStatus(q->iv); mHeu.getTxCh(q->iv); testMode = mHeu.getTestModeEnabled(); mGotFragment = false; - mFirstTry = mFirstTry ? false : ( (IV_HM == q->iv->ivGen) || (IV_MI == q->iv->ivGen) ) && (q->iv->isAvailable()); //) || (millis() < 120000));} + q->iv->mGotLastMsg = false; + mFirstTry = mFirstTry ? false : ( ( (IV_HM == q->iv->ivGen) || (IV_MI == q->iv->ivGen) ) && (q->iv->isAvailable()) || (millis() < 120000) ); if(NULL == q->iv->radio) cmdDone(true); // can't communicate while radio is not defined! mState = States::START; @@ -83,12 +87,33 @@ class Communication : public CommQueue<> { q->iv->radio->prepareDevInformCmd(q->iv, q->cmd, q->ts, q->iv->alarmLastId, false); if(!testMode) q->iv->radioStatistics.txCnt++; - mWaitTimeout = millis() + timeout; + mWaitTimeout = millis() + timeout; + mWaitTimeout_min = millis() + timeout_min; setAttempt(); mState = States::WAIT; break; case States::WAIT: + if(millis() > mWaitTimeout_min) { + if(!mGotFragment) { // nothing received yet? + if(q->iv->radio->get()) { // radio received sth.? + mGotFragment = true; + if(q->iv->mGotLastMsg) { + //mState = States::CHECK_FRAMES; + mWaitTimeout = mWaitTimeout_min; + } + } + } else if(mFirstTry) { + DPRINT_IVID(DBG_INFO, q->iv->id); + DBGPRINTLN(F("second try")); + mFirstTry = false; + if(!testMode) + q->iv->radioStatistics.retransmits++; // got nothing + mState = States::START; + break; + } + + } if(millis() < mWaitTimeout) return; mState = States::CHECK_FRAMES; @@ -102,7 +127,7 @@ class Communication : public CommQueue<> { DBGPRINT(String(millis() - mWaitTimeout + timeout)); DBGPRINTLN(F("ms")); - if(!mGotFragment && !mFirstTry) { + if(!mGotFragment) { // && !mFirstTry) { if(!testMode) q->iv->radioStatistics.rxFailNoAnser++; // got nothing mHeu.setGotNothing(q->iv); @@ -140,7 +165,7 @@ class Communication : public CommQueue<> { DBGPRINT(F(", ")); DBGPRINT(String(p->rssi)); DBGPRINT(F("dBm | ")); - ah::dumpBuf(p->packet, p->len); + ah::dumpBuf(p->packet, p->len, 1, 8, "#"+String(q->iv->id)); if(checkIvSerial(&p->packet[1], q->iv)) { if(!testMode) @@ -178,39 +203,37 @@ class Communication : public CommQueue<> { break; case States::CHECK_PACKAGE: + uint8_t framnr = 0; if(0 == mMaxFrameId) { - setAttempt(); - - DPRINT_IVID(DBG_WARN, q->iv->id); - DBGPRINT(F("frame missing: request retransmit (")); - DBGPRINT(String(q->attempts)); - DBGPRINTLN(F(" attempts left)")); - uint8_t i = 0; while(i < MAX_PAYLOAD_ENTRIES) { if(mLocalBuf[i].len == 0) + framnr = i+1; break; i++; } - - sendRetransmit(q, i); - return; } - for(uint8_t i = 0; i < mMaxFrameId; i++) { - if(mLocalBuf[i].len == 0) { - setAttempt(); + if(!framnr) { + for(uint8_t i = 0; i < mMaxFrameId; i++) { + if(mLocalBuf[i].len == 0) { + framnr = i+1; + break; + } + } + } - DPRINT_IVID(DBG_WARN, q->iv->id); - DBGPRINT(F("frame ")); - DBGPRINT(String(i + 1)); - DBGPRINT(F(" missing: request retransmit (")); - DBGPRINT(String(q->attempts)); - DBGPRINTLN(F(" attempts left)")); + if(framnr) { + setAttempt(); - sendRetransmit(q, i); - return; - } + 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); + return; } mHeu.setGotAll(q->iv); @@ -257,8 +280,9 @@ class Communication : public CommQueue<> { return; // CRC8 is wrong, frame invalid } - if((*frameId & ALL_FRAMES) == ALL_FRAMES) + if((*frameId & ALL_FRAMES) == ALL_FRAMES) { mMaxFrameId = (*frameId & 0x7f); + } frame_t *f = &mLocalBuf[(*frameId & 0x7f) - 1]; memcpy(f->buf, &p->packet[10], p->len-11); @@ -413,9 +437,6 @@ class Communication : public CommQueue<> { inline void miHwDecode(packet_t *p, const queue_s *q) { record_t<> *rec = q->iv->getRecordStruct(InverterDevInform_All); // choose the record structure rec->ts = q->ts; - //mPayload[iv->id].gotFragment = true; - uint8_t multi_parts = 0; - /* Polling the device software and hardware version number command start byte Command word routing address target address User data check end byte @@ -458,14 +479,13 @@ class Communication : public CommQueue<> { q->iv->isConnected = true; //if(mSerialDebug) { DPRINT_IVID(DBG_INFO, q->iv->id); - DPRINT(DBG_INFO,F("HW_VER is ")); + DBGPRINT(F("HW_VER is ")); DBGPRINTLN(String((p->packet[24] << 8) + p->packet[25])); //} record_t<> *rec = q->iv->getRecordStruct(InverterDevInform_Simple); // choose the record structure rec->ts = q->ts; q->iv->setValue(1, rec, (uint32_t) ((p->packet[24] << 8) + p->packet[25])/1); - //mPayload[iv->id].multi_parts +=4; - multi_parts +=4; + q->iv->miMultiParts +=4; } else if ( p->packet[9] == 0x01 || p->packet[9] == 0x10 ) {//second frame for MI, 3rd gen. answers in 0x10 DPRINT_IVID(DBG_INFO, q->iv->id); if ( p->packet[9] == 0x01 ) { @@ -486,19 +506,19 @@ class Communication : public CommQueue<> { //if(mSerialDebug) { DPRINT(DBG_INFO,F("HW_FB_TLmValue ")); DBGPRINTLN(String((p->packet[14] << 8) + p->packet[15])); - DPRINT(DBG_INFO,F("HW_FB_ReSPRT ")); + DBGPRINT(F("HW_FB_ReSPRT ")); DBGPRINTLN(String((p->packet[16] << 8) + p->packet[17])); - DPRINT(DBG_INFO,F("HW_GridSamp_ResValule ")); + DBGPRINT(F("HW_GridSamp_ResValule ")); DBGPRINTLN(String((p->packet[18] << 8) + p->packet[19])); - DPRINT(DBG_INFO,F("HW_ECapValue ")); + DBGPRINT(F("HW_ECapValue ")); DBGPRINTLN(String((p->packet[20] << 8) + p->packet[21])); - DPRINT(DBG_INFO,F("Matching_APPFW_PN ")); + DBGPRINT(F("Matching_APPFW_PN ")); DBGPRINTLN(String((uint32_t) (((p->packet[22] << 8) | p->packet[23]) << 8 | p->packet[24]) << 8 | p->packet[25])); //} - //notify(InverterDevInform_Simple, iv); - //mPayload[iv->id].multi_parts +=2; - multi_parts +=2; - //notify(InverterDevInform_All, iv); + if(NULL != mCbPayload) + (mCbPayload)(InverterDevInform_All, q->iv); + q->iv->miMultiParts +=2; + } else { DBGPRINTLN(F("3rd gen. inverter!")); } @@ -515,21 +535,24 @@ class Communication : public CommQueue<> { //if(mSerialDebug) { DPRINT(DBG_INFO,F("APPFW_MINVER ")); DBGPRINTLN(String((p->packet[10] << 8) + p->packet[11])); - DPRINT(DBG_INFO,F("HWInfoAddr ")); + DBGPRINT(F("HWInfoAddr ")); DBGPRINTLN(String((p->packet[12] << 8) + p->packet[13])); - DPRINT(DBG_INFO,F("PNInfoCRC_gusv ")); + DBGPRINT(F("PNInfoCRC_gusv ")); DBGPRINTLN(String((p->packet[14] << 8) + p->packet[15])); //} - //mPayload[iv->id].multi_parts++; - multi_parts++; + if(NULL != mCbPayload) + (mCbPayload)(InverterDevInform_Simple, q->iv); + q->iv->miMultiParts++; } - if(multi_parts > 5) { + if(q->iv->miMultiParts > 5) { cmdDone(true); mState = States::RESET; q->iv->radioStatistics.rxSuccess++; mHeu.setGotAll(q->iv); + q->iv->miMultiParts = 0; } else { mHeu.setGotFragment(q->iv); + mState = States::WAIT; } /*if (mPayload[iv->id].multi_parts > 5) { @@ -568,9 +591,8 @@ class Communication : public CommQueue<> { q->iv->setValue(q->iv->getPosByChFld(0, FLD_T, rec), rec, (float) ((int16_t)(p->packet[21] << 8) + p->packet[22])/10); q->iv->setValue(q->iv->getPosByChFld(0, FLD_IRR, rec), rec, (float) (calcIrradiation(q->iv, datachan))); - //mPayload[q->iv->id].rssi[(datachan-1)] = p->rssi; - if (datachan == 1) //mPayload[q->iv->id].rssi[(datachan-1)] = p->rssi; + if (datachan == 1) q->iv->rssi = p->rssi; else if(q->iv->rssi > p->rssi) q->iv->rssi = p->rssi; @@ -597,6 +619,7 @@ class Communication : public CommQueue<> { } else if((p->packet[0] == (MI_REQ_CH1 + ALL_FRAMES)) && (q->iv->type == INV_TYPE_2CH)) { //addImportant(q->iv, MI_REQ_CH2); miNextRequest(MI_REQ_CH2, q); + //use also miMultiParts here for better statistics? mHeu.setGotFragment(q->iv); } else { // first data msg for 1ch, 2nd for 2ch miComplete(q->iv); @@ -604,25 +627,24 @@ class Communication : public CommQueue<> { } inline void miNextRequest(uint8_t cmd, const queue_s *q) { - //setAttempt(); + incrAttempt(); // if function is called, we got something, and we necessarily need more transmissions for MI types... DPRINT_IVID(DBG_WARN, q->iv->id); DBGPRINT(F("next request (")); DBGPRINT(String(q->attempts)); DBGPRINT(F(" attempts left): 0x")); DBGHEXLN(cmd); - if(q->attempts) { + //if(q->attempts) { q->iv->radio->sendCmdPacket(q->iv, cmd, 0x00, true); q->iv->radioStatistics.retransmits++; mWaitTimeout = millis() + MI_TIMEOUT; - //chgCmd(Inverter<> *iv, uint8_t cmd, bool delOnPop = true) chgCmd(cmd); mState = States::WAIT; - } else { + /*} else { add(q, true); cmdDone(); mState = States::RESET; - } + }*/ } inline void miStsConsolidate(const queue_s *q, uint8_t stschan, record_t<> *rec, uint8_t uState, uint8_t uEnum, uint8_t lState = 0, uint8_t lEnum = 0) { @@ -699,13 +721,10 @@ class Communication : public CommQueue<> { inline void miComplete(Inverter<> *iv) { - //if ( mPayload[iv->id].complete ) - // return; //if we got second message as well in repreated attempt - //mPayload[iv->id].complete = true; - //if (mSerialDebug) { + if (iv->radio->isSerialDebug()) { DPRINT_IVID(DBG_INFO, iv->id); DBGPRINTLN(F("got all data msgs")); - //} + } record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); iv->setValue(iv->getPosByChFld(0, FLD_YD, rec), rec, calcYieldDayCh0(iv,0)); @@ -751,7 +770,8 @@ class Communication : public CommQueue<> { private: States mState = States::RESET; uint32_t *mTimestamp; - uint32_t mWaitTimeout = 0; + uint32_t mWaitTimeout = 0; + uint32_t mWaitTimeout_min = 0; std::array mLocalBuf; bool mGotFragment = false; bool mFirstTry = false; diff --git a/src/hm/Heuristic.h b/src/hm/Heuristic.h index 7bf9f4a9..3ad249b9 100644 --- a/src/hm/Heuristic.h +++ b/src/hm/Heuristic.h @@ -62,7 +62,7 @@ class Heuristic { void printStatus(Inverter<> *iv) { DPRINT_IVID(DBG_INFO, iv->id); - DBGPRINT(F("CH qualities:")); + DBGPRINT(F("Radio infos:")); for(uint8_t i = 0; i < RF_MAX_CHANNEL_ID; i++) { DBGPRINT(F(" ")); DBGPRINT(String(iv->txRfQuality[i])); @@ -74,7 +74,9 @@ class Heuristic { DBGPRINT(F(", f: ")); DBGPRINT(String(iv->radioStatistics.rxFail)); DBGPRINT(F(", n: ")); - DBGPRINTLN(String(iv->radioStatistics.rxFailNoAnser)); + DBGPRINT(String(iv->radioStatistics.rxFailNoAnser)); + DBGPRINT(F(" | p: ")); // better debugging for helpers... + DBGPRINTLN(String(iv->config->powerLevel)); } bool getTestModeEnabled(void) { diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h index f3d149c4..88a19a1b 100644 --- a/src/hm/hmInverter.h +++ b/src/hm/hmInverter.h @@ -125,6 +125,8 @@ class Inverter { uint16_t alarmCnt; // counts the total number of occurred alarms uint16_t alarmLastId; // lastId which was received int8_t rssi; // RSSI + uint8_t miMultiParts; // helper info for MI multiframe msgs + bool mGotLastMsg; // shows if inverter has already finished transmission cycle Radio *radio; // pointer to associated radio class statistics_t radioStatistics; // information about transmitted, failed, ... packets int8_t txRfQuality[5]; // heuristics tx quality (check 'Heuristics.h') @@ -150,8 +152,11 @@ class Inverter { alarmCnt = 0; alarmLastId = 0; rssi = -127; + miMultiParts = 0; + mGotLastMsg = false; radio = NULL; commEnabled = true; + memset(&radioStatistics, 0, sizeof(statistics_t)); memset(txRfQuality, -6, 5); diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h index a55c7d3c..a51504df 100644 --- a/src/hm/hmRadio.h +++ b/src/hm/hmRadio.h @@ -257,12 +257,14 @@ class HmRadio : public Radio { isLastPackage = (p.packet[9] > ALL_FRAMES); // > ALL_FRAMES indicates last packet received else if (p.packet[0] == ( 0x0f + ALL_FRAMES) ) // response from MI get information command isLastPackage = (p.packet[9] > 0x10); // > 0x10 indicates last packet received - else if ((p.packet[0] != 0x88) && (p.packet[0] != 0x92)) // ignore fragment number zero and MI status messages //#0 was p.packet[0] != 0x00 && + else if ((p.packet[0] != 0x88) && (p.packet[0] != 0x92)) // ignore MI status messages //#0 was p.packet[0] != 0x00 && isLastPackage = true; // response from dev control command } } yield(); } + if(isLastPackage) + mLastIv->mGotLastMsg = true; return isLastPackage; } @@ -280,7 +282,7 @@ class HmRadio : public Radio { DBGPRINT(" CH"); DBGPRINT(String(mTxChIdx)); DBGPRINT(F(" | ")); - ah::dumpBuf(mTxBuf, len); + ah::dumpBuf(mTxBuf, len, 1, 4, "#"+String(iv->id)); } mNrf24.stopListening(); @@ -304,6 +306,7 @@ class HmRadio : public Radio { uint8_t mRfChLst[RF_CHANNELS] = {03, 23, 40, 61, 75}; // channel List:2403, 2423, 2440, 2461, 2475MHz uint8_t mTxChIdx = 0; uint8_t mRxChIdx = 0; + bool mGotLastMsg = false; uint32_t mMillis; SPIClass* mSpi; diff --git a/src/hm/radio.h b/src/hm/radio.h index 07317e8c..e4beb071 100644 --- a/src/hm/radio.h +++ b/src/hm/radio.h @@ -38,6 +38,10 @@ class Radio { mSerialDebug = true; } + bool isSerialDebug() { + return mSerialDebug; + } + void sendCmdPacket(Inverter<> *iv, uint8_t mid, uint8_t pid, bool isRetransmit, bool appendCrc16=true) { initPacket(getIvId(iv), mid, pid); sendPacket(iv, 10, isRetransmit, appendCrc16); diff --git a/src/utils/helper.cpp b/src/utils/helper.cpp index 4050c999..c7aefc1c 100644 --- a/src/utils/helper.cpp +++ b/src/utils/helper.cpp @@ -86,9 +86,12 @@ namespace ah { return ret; } - void dumpBuf(uint8_t buf[], uint8_t len) { + void dumpBuf(uint8_t buf[], uint8_t len, uint8_t firstRepl, uint8_t lastRepl, String repl) { for(uint8_t i = 0; i < len; i++) { - DHEX(buf[i]); + if(i < firstRepl || i > lastRepl) + DHEX(buf[i]); + else + DBGPRINT(repl); DBGPRINT(" "); } DBGPRINTLN(""); diff --git a/src/utils/helper.h b/src/utils/helper.h index 252ca9fe..296729db 100644 --- a/src/utils/helper.h +++ b/src/utils/helper.h @@ -45,7 +45,7 @@ namespace ah { String getDateTimeStrFile(time_t t); String getTimeStr(time_t t); uint64_t Serial2u64(const char *val); - void dumpBuf(uint8_t buf[], uint8_t len); + void dumpBuf(uint8_t buf[], uint8_t len, uint8_t firstRepl = 0, uint8_t lastRepl = 0, String repl = ""); } #endif /*__HELPER_H__*/