Skip to content

Commit

Permalink
Merge branch 'rejoe2-dynamic-retries-offset' into development03
Browse files Browse the repository at this point in the history
  • Loading branch information
lumapu committed Jan 31, 2024
2 parents 163a9e4 + 7c1ebfb commit ac58f2f
Show file tree
Hide file tree
Showing 10 changed files with 212 additions and 62 deletions.
4 changes: 2 additions & 2 deletions src/hm/CommQueue.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
#include "../utils/dbg.h"

#define DEFAULT_ATTEMPS 5
#define MORE_ATTEMPS_ALARMDATA 8
#define MORE_ATTEMPS_GRIDONPROFILEPARA 5
#define MORE_ATTEMPS_ALARMDATA 3 // 8
#define MORE_ATTEMPS_GRIDONPROFILEPARA 0 // 5

template <uint8_t N=100>
class CommQueue {
Expand Down
77 changes: 54 additions & 23 deletions src/hm/Communication.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,11 @@ class Communication : public CommQueue<> {
q->iv->mGotFragment = false;
q->iv->mGotLastMsg = false;
q->iv->curFrmCnt = 0;
q->iv->radioStatistics.txCnt++;
mIsRetransmit = false;
if(NULL == q->iv->radio)
cmdDone(false); // can't communicate while radio is not defined!
mFirstTry = q->iv->isAvailable();
mFirstTry = INV_RADIO_TYPE_NRF == q->iv->ivRadioType && q->iv->isAvailable();
q->iv->mCmd = q->cmd;
q->iv->mIsSingleframeReq = false;
mFramesExpected = getFramesExpected(q); // function to get expected frame count.
Expand All @@ -112,13 +113,13 @@ class Communication : public CommQueue<> {
} else
q->iv->radio->prepareDevInformCmd(q->iv, q->cmd, q->ts, q->iv->alarmLastId, false);

q->iv->radioStatistics.txCnt++;
//q->iv->radioStatistics.txCnt++;
q->iv->radio->mRadioWaitTime.startTimeMonitor(mTimeout);
if(!mIsRetransmit && (q->cmd == AlarmData) || (q->cmd == GridOnProFilePara))
incrAttempt(q->cmd == AlarmData? MORE_ATTEMPS_ALARMDATA : MORE_ATTEMPS_GRIDONPROFILEPARA);

mIsRetransmit = false;
setAttempt();
if((q->cmd == AlarmData) || (q->cmd == GridOnProFilePara))
incrAttempt(q->cmd == AlarmData? MORE_ATTEMPS_ALARMDATA : MORE_ATTEMPS_GRIDONPROFILEPARA);
mState = States::WAIT;
break;

Expand All @@ -129,13 +130,14 @@ class Communication : public CommQueue<> {
break;

case States::CHECK_FRAMES: {
if((q->iv->radio->mBufCtrl.empty() && !mIsRetransmit) || (0 == q->attempts)) { // radio buffer empty or no more answers
if((q->iv->radio->mBufCtrl.empty() && !mIsRetransmit) ) { // || (0 == q->attempts)) { // radio buffer empty. No more answers will be checked later
if(*mSerialDebug) {
DPRINT_IVID(DBG_INFO, q->iv->id);
DBGPRINT(F("request timeout: "));
DBGPRINT(String(q->iv->radio->mRadioWaitTime.getRunTime()));
DBGPRINTLN(F("ms"));
}

if(!q->iv->mGotFragment) {
if(INV_RADIO_TYPE_CMT == q->iv->ivRadioType) {
#if defined(ESP32)
Expand All @@ -146,18 +148,20 @@ class Communication : public CommQueue<> {
mWaitTime.startTimeMonitor(1000);
#endif
} else {
mHeu.setIvRetriesBad(q->iv);
if(IV_MI == q->iv->ivGen)
q->iv->mIvTxCnt++;

if(mFirstTry) {
mFirstTry = false;
setAttempt();
if(q->attempts < 3 || !q->iv->isProducing())
mFirstTry = false;
mHeu.evalTxChQuality(q->iv, false, 0, 0);
q->iv->radioStatistics.rxFailNoAnser++;
mHeu.getTxCh(q->iv);
//q->iv->radioStatistics.rxFailNoAnser++; // should only be one of fail or retransmit.
//q->iv->radioStatistics.txCnt--;
q->iv->radioStatistics.retransmits++;
q->iv->radio->mRadioWaitTime.stopTimeMonitor();
mState = States::START;

return;
}
}
Expand All @@ -178,8 +182,11 @@ class Communication : public CommQueue<> {
q->iv->mDtuRxCnt++;

if (p->packet[0] == (TX_REQ_INFO + ALL_FRAMES)) { // response from get information command
if(parseFrame(p))
if(parseFrame(p)) {
q->iv->curFrmCnt++;
if(!mIsRetransmit && (p->packet[9] == 0x02 || p->packet[9] == 0x82) && p->millis < LIMIT_FAST_IV)
mHeu.setIvRetriesGood(q->iv,p->millis < LIMIT_VERYFAST_IV);
}
} else if (p->packet[0] == (TX_REQ_DEVCONTROL + ALL_FRAMES)) { // response from dev control command
if(parseDevCtrl(p, q))
closeRequest(q, true);
Expand All @@ -200,7 +207,6 @@ class Communication : public CommQueue<> {
if(q->iv->ivGen != IV_MI) {
mState = States::CHECK_PACKAGE;
} else {
bool fastNext = true;
if(q->iv->miMultiParts < 6) {
mState = States::WAIT;
if((q->iv->radio->mRadioWaitTime.isTimeout() && mIsRetransmit) || !mIsRetransmit) {
Expand All @@ -213,12 +219,8 @@ class Communication : public CommQueue<> {
|| ((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);
fastNext = false;
}
if(fastNext)
miNextRequest(q->iv->type == INV_TYPE_4CH ? MI_REQ_4CH : MI_REQ_CH1, q);
else
closeRequest(q, true);
closeRequest(q, true);
}
}

Expand Down Expand Up @@ -250,10 +252,33 @@ class Communication : public CommQueue<> {
if(framnr) {
if(0 == q->attempts) {
DPRINT_IVID(DBG_INFO, q->iv->id);
DBGPRINT(F("no attempts left"));
DBGPRINTLN(F("timeout, no attempts left"));
closeRequest(q, false);
return;
}
//count missing frames
if(!q->iv->mIsSingleframeReq && q->iv->ivRadioType == INV_RADIO_TYPE_NRF) { // already checked?
uint8_t missedFrames = 0;
for(uint8_t i = 0; i < q->iv->radio->mFramesExpected; i++) {
if(mLocalBuf[i].len == 0)
missedFrames++;
}
if(missedFrames > 3 || (q->cmd == RealTimeRunData_Debug && missedFrames > 1) || (missedFrames > 1 && missedFrames + 2 > q->attempts)) {
if(*mSerialDebug) {
DPRINT_IVID(DBG_INFO, q->iv->id);
DBGPRINT(String(missedFrames));
DBGPRINT(F(" frames missing "));
DBGPRINTLN(F("-> complete retransmit"));
}
mHeu.evalTxChQuality(q->iv, false, (q->attemptsMax - 1 - q->attempts), q->iv->curFrmCnt);
q->iv->radioStatistics.txCnt--;
q->iv->radioStatistics.retransmits++;
mCompleteRetry = true;
mState = States::RESET;
return;
}
}

setAttempt();

if(*mSerialDebug) {
Expand Down Expand Up @@ -410,6 +435,8 @@ class Communication : public CommQueue<> {
}

inline bool parseMiFrame(packet_t *p, const queue_s *q) {
if(!mIsRetransmit && p->packet[9] == 0x00 && p->millis < LIMIT_FAST_IV_MI) //first frame is fast?
mHeu.setIvRetriesGood(q->iv,p->millis < LIMIT_VERYFAST_IV_MI);
if ((p->packet[0] == MI_REQ_CH1 + ALL_FRAMES)
|| (p->packet[0] == MI_REQ_CH2 + ALL_FRAMES)
|| ((p->packet[0] >= (MI_REQ_4CH + ALL_FRAMES))
Expand All @@ -429,7 +456,6 @@ class Communication : public CommQueue<> {
record_t<> *rec = q->iv->getRecordStruct(RealTimeRunData_Debug); // choose the record structure
rec->ts = q->ts;
miStsConsolidate(q, ((p->packet[0] == 0x88) ? 1 : 2), rec, p->packet[10], p->packet[12], p->packet[9], p->packet[11]);
//mHeu.setGotFragment(q->iv); only do this when we are through the cycle?
}

return true;
Expand Down Expand Up @@ -493,6 +519,7 @@ class Communication : public CommQueue<> {

} else
DBGPRINTLN(F("-> complete retransmit"));
mCompleteRetry = true;
mState = States::RESET;
return;
}
Expand Down Expand Up @@ -592,7 +619,7 @@ class Communication : public CommQueue<> {
mHeu.evalTxChQuality(q->iv, crcPass, (q->attemptsMax - 1 - q->attempts), q->iv->curFrmCnt);
if(crcPass)
q->iv->radioStatistics.rxSuccess++;
else if(q->iv->mGotFragment)
else if(q->iv->mGotFragment || mCompleteRetry)
q->iv->radioStatistics.rxFail++; // got no complete payload
else
q->iv->radioStatistics.rxFailNoAnser++; // got nothing
Expand All @@ -607,6 +634,7 @@ class Communication : public CommQueue<> {
q->iv->mGotLastMsg = false;
q->iv->miMultiParts = 0;
mIsRetransmit = false;
mCompleteRetry = false;
mState = States::RESET;
DBGPRINTLN(F("-----"));
}
Expand Down Expand Up @@ -820,8 +848,9 @@ class Communication : public CommQueue<> {
DBGHEXLN(cmd);
}

if(q->iv->miMultiParts == 7)
q->iv->radioStatistics.rxSuccess++;
/*if(q->iv->miMultiParts > 5) //if(q->iv->miMultiParts == 7)
q->iv->radioStatistics.rxSuccess++;*/
q->iv->radioStatistics.ivSent++;

mFramesExpected = getFramesExpected(q);
q->iv->radio->setExpectedFrames(mFramesExpected);
Expand All @@ -846,6 +875,7 @@ class Communication : public CommQueue<> {
}

q->iv->radio->sendCmdPacket(q->iv, q->cmd, 0x00, true);
q->iv->radioStatistics.retransmits++;

q->iv->radio->mRadioWaitTime.startTimeMonitor(DURATION_TXFRAME + DURATION_ONEFRAME + duration_reserve[q->iv->ivRadioType]);
mIsRetransmit = false;
Expand Down Expand Up @@ -999,8 +1029,9 @@ class Communication : public CommQueue<> {
uint16_t *mInverterGap;
TimeMonitor mWaitTime = TimeMonitor(0, true); // start as expired (due to code in RESET state)
std::array<frame_t, MAX_PAYLOAD_ENTRIES> mLocalBuf;
bool mFirstTry = false; // see, if we should do a second try
bool mIsRetransmit = false; // we already had waited one complete cycle
bool mFirstTry = false; // see, if we should do a second try
bool mCompleteRetry = false; // remember if we did request a complete retransmission
bool mIsRetransmit = false; // we already had waited one complete cycle
uint8_t mMaxFrameId;
uint8_t mFramesExpected = 12; // 0x8c was highest last frame for alarm data
uint16_t mTimeout = 0; // calculating that once should be ok
Expand Down
48 changes: 46 additions & 2 deletions src/hm/Heuristic.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
class Heuristic {
public:
uint8_t getTxCh(Inverter<> *iv) {
if((IV_HMS == iv->ivGen) || (IV_HMT == iv->ivGen))
return 0; // not used for these inverter types
if(iv->ivRadioType != INV_RADIO_TYPE_NRF)
return 0; // not used for other than nRF inverter types

HeuristicInv *ih = &iv->heuristics;

Expand Down Expand Up @@ -66,6 +66,8 @@ class Heuristic {
ih->testPeriodFailCnt = 0;
}

iv->radio->mTxRetriesNext = getIvRetries(iv);

return id2Ch(ih->txRfChId);
}

Expand Down Expand Up @@ -155,6 +157,48 @@ class Heuristic {
DBGPRINTLN(String(iv->config->powerLevel));
}

uint8_t getIvRetries(Inverter<> *iv) {
if(iv->heuristics.rxSpeeds[0])
return RETRIES_VERYFAST_IV;
if(iv->heuristics.rxSpeeds[1])
return RETRIES_FAST_IV;
return 15;
}

void setIvRetriesGood(Inverter<> *iv, bool veryGood) {
if(iv->ivRadioType != INV_RADIO_TYPE_NRF)
return; // not used for other than nRF inverter types

if(iv->heuristics.rxSpeedCnt[veryGood] > 9)
return;
iv->heuristics.rxSpeedCnt[veryGood]++;
iv->heuristics.rxSpeeds[veryGood] = true;
}

void setIvRetriesBad(Inverter<> *iv) {
if(iv->ivRadioType != INV_RADIO_TYPE_NRF)
return; // not used for other than nRF inverter types

if(iv->heuristics.rxSpeedCnt[0]) {
iv->heuristics.rxSpeedCnt[0]--;
return;
}
if(iv->heuristics.rxSpeeds[0]) {
iv->heuristics.rxSpeeds[0] = false;
return;
}

if(iv->heuristics.rxSpeedCnt[1]) {
iv->heuristics.rxSpeedCnt[1]--;
return;
}
if(iv->heuristics.rxSpeeds[1]) {
iv->heuristics.rxSpeeds[1] = false;
return;
}
return;
}

private:
bool isNewTxCh(HeuristicInv *ih) {
return ih->txRfChId != ih->lastBestTxChId;
Expand Down
3 changes: 3 additions & 0 deletions src/hm/HeuristicInv.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ class HeuristicInv {
uint8_t testChId = 0;
int8_t saveOldTestQuality = -6;
uint8_t lastRxFragments = 0;
bool rxSpeeds[2] = {false,false}; // is inverter responding very fast respective fast?
uint8_t rxSpeedCnt[2] = {0,0}; // count how many messages had been received very fast respective fast (10 max)

};

#endif /*__HEURISTIC_INV_H__*/
10 changes: 9 additions & 1 deletion src/hm/hmDefines.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,15 @@ enum {INV_RADIO_TYPE_NRF = 0, INV_RADIO_TYPE_CMT};
#define DURATION_TXFRAME 85 // timeout parameter for first transmission and first expected frame (time to first channel switch from tx start!) (ms)
#define DURATION_LISTEN_MIN 5 // time to stay at least on a listening channel (ms)
#define DURATION_PAUSE_LASTFR 45 // how long to pause after last frame (ms)
const uint8_t duration_reserve[2] = {115,115};
const uint8_t duration_reserve[2] = {65,115};

#define LIMIT_FAST_IV 85 // time limit to qualify an inverter as very fast answering inverter
#define LIMIT_VERYFAST_IV 70 // time limit to qualify an inverter as very fast answering inverter
#define LIMIT_FAST_IV_MI 35 // time limit to qualify a MI type inverter as fast answering inverter
#define LIMIT_VERYFAST_IV_MI 22 // time limit to qualify a MI type inverter as very fast answering inverter
#define RETRIES_FAST_IV 12 // how often shall a message be automatically retransmitted by the nRF (fast answering inverter)
#define RETRIES_VERYFAST_IV 9 // how often shall a message be automatically retransmitted by the nRF (very fast answering inverter)


typedef struct {
uint8_t fieldId; // field id
Expand Down
Loading

0 comments on commit ac58f2f

Please sign in to comment.