From 0ec95f83f0b59948d9369544982724b6930c6b65 Mon Sep 17 00:00:00 2001 From: no name Date: Sat, 26 Aug 2023 16:55:01 +0200 Subject: [PATCH] Send Channel evaluation is now part of inverter. Additional test period to find best send channel. --- src/app.cpp | 9 ++- src/hm/hmDefines.h | 3 + src/hm/hmInverter.h | 146 ++++++++++++++++++++++++++++++++++++++++++++ src/hm/hmPayload.h | 30 ++++++--- src/hm/hmRadio.h | 118 +++++------------------------------ src/hm/miPayload.h | 48 ++++++++++++--- 6 files changed, 230 insertions(+), 124 deletions(-) diff --git a/src/app.cpp b/src/app.cpp index 98ffaec8..bd7d3965 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -346,13 +346,14 @@ void app::tickMinute(void) { //----------------------------------------------------------------------------- void app::tickMidnight(void) { + Inverter<> *iv; + if (mConfig->inst.rstYieldMidNight) { // only if 'reset values at midnight is enabled' uint32_t localTime = gTimezone.toLocal(mTimestamp); uint32_t nxtTrig = gTimezone.toUTC(localTime - (localTime % 86400) + 86400); // next midnight local time onceAt(std::bind(&app::tickMidnight, this), nxtTrig, "mid2"); - Inverter<> *iv; // set values to zero, except yield total for (uint8_t id = 0; id < mSys.getNumInverters(); id++) { iv = mSys.getInverterByPos(id); @@ -367,7 +368,11 @@ void app::tickMidnight(void) { mMqtt.tickerMidnight(); #endif } - mSys.Radio.resetSendChannelQuality(); + for (uint8_t id = 0; id < mSys.getNumInverters(); id++) { + if ((iv = mSys.getInverterByPos(id))) { + iv->cleanupRxInfo(); + } + } mSys.cleanup_history(); #ifdef AHOY_SML_OBIS_SUPPORT // design: allways try to clean up diff --git a/src/hm/hmDefines.h b/src/hm/hmDefines.h index c7f853f5..ab2069cc 100644 --- a/src/hm/hmDefines.h +++ b/src/hm/hmDefines.h @@ -9,6 +9,9 @@ #include "../utils/dbg.h" #include +#define RF_CHANNELS 5 +#define AHOY_RF24_DEF_TX_CHANNEL 2 // 40 +#define AHOY_RF24_DEF_RX_CHANNEL 0 // 3 // inverter generations enum {IV_HM = 0, IV_MI}; diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h index 3ea6e12a..51328508 100644 --- a/src/hm/hmInverter.h +++ b/src/hm/hmInverter.h @@ -16,6 +16,21 @@ #include #include "../config/settings.h" +// Send channel heuristic has 2 strategies: +// - Evaluation of current send channel quality due to receive situation and compare with others +#define RF_TX_CHAN_MAX_QUALITY 4 +#define RF_TX_CHAN_MIN_QUALITY -6 +#define RF_TX_CHAN_QUALITY_GOOD 2 +#define RF_TX_CHAN_QUALITY_OK 1 +#define RF_TX_CHAN_QUALITY_NEUTRAL 0 +#define RF_TX_CHAN_QUALITY_LOW -1 +#define RF_TX_CHAN_QUALITY_BAD -2 +// - if more than _MAX_FAIL_CNT problems during _MAX_SEND_CNT test period: try another chan and see if it works (even) better +#define RF_TEST_PERIOD_MAX_FAIL_CNT 5 +#define RF_TEST_PERIOD_MAX_SEND_CNT 50 +// mark current test chan as 1st use during this test period +#define RF_TX_TEST_CHAN_1ST_USE 0xff + /** * For values which are of interest and not transmitted by the inverter can be * calculated automatically. @@ -134,6 +149,13 @@ class Inverter { uint16_t alarmCode; // last Alarm uint32_t alarmStart; uint32_t alarmEnd; + int8_t mTxChanQuality[RF_CHANNELS]; // qualities of send channels + uint8_t mBestTxChanIndex; // current send chan index + uint8_t mLastBestTxChanIndex; // last send chan index + uint8_t mTestTxChanIndex; // Index of last test chan (or special value RF_TX_TEST_CHAN for 1st use) + uint8_t mTestPeriodSendCnt; // increment of current test period + uint8_t mTestPeriodFailCnt; // no of fails during current test period + uint8_t mSaveOldTestChanQuality; // original quality of current TestTxChanIndex Inverter() { ivGen = IV_HM; @@ -146,6 +168,8 @@ class Inverter { alarmMesIndex = 0; isConnected = false; alarmCode = 0; + mBestTxChanIndex = AHOY_RF24_DEF_TX_CHANNEL ? AHOY_RF24_DEF_TX_CHANNEL - 1 : RF_CHANNELS - 1; + mLastBestTxChanIndex = AHOY_RF24_DEF_TX_CHANNEL; } ~Inverter() { @@ -582,6 +606,128 @@ class Inverter { } } + bool isNewTxChan () + { + return mBestTxChanIndex != mLastBestTxChanIndex; + } + + uint8_t getNextTxChanIndex (void) + { + // start with the next index: round robbin in case of same 'best' quality + uint8_t curIndex = (mBestTxChanIndex + 1) % RF_CHANNELS; + + mLastBestTxChanIndex = mBestTxChanIndex; + mBestTxChanIndex = curIndex; + curIndex = (curIndex + 1) % RF_CHANNELS; + for (uint16_t i=1; i mTxChanQuality[mBestTxChanIndex]) { + mBestTxChanIndex = curIndex; + } + curIndex = (curIndex + 1) % RF_CHANNELS; + } + if ((mBestTxChanIndex == mLastBestTxChanIndex) && (mTestPeriodSendCnt >= RF_TEST_PERIOD_MAX_SEND_CNT)) { + if (mTestPeriodFailCnt > RF_TEST_PERIOD_MAX_FAIL_CNT) { + // try round robbin another chan and see if it works even better + mTestTxChanIndex = (mTestTxChanIndex + 1) % RF_CHANNELS; + if (mTestTxChanIndex == mBestTxChanIndex) { + mTestTxChanIndex = (mTestTxChanIndex + 1) % RF_CHANNELS; + } + // give it a fair chance but remember old status in case of immediate fail + mSaveOldTestChanQuality = mTxChanQuality[mTestTxChanIndex]; + mTxChanQuality[mTestTxChanIndex] = mTxChanQuality[mBestTxChanIndex]; + mBestTxChanIndex = mTestTxChanIndex; + mTestTxChanIndex = RF_TX_TEST_CHAN_1ST_USE; // mark the chan as a test and as 1st use during new test period + DPRINTLN (DBG_INFO, "Try Ch Idx " + String (mBestTxChanIndex)); + } + // design: start new test period + mTestPeriodSendCnt = 0; + mTestPeriodFailCnt = 0; + } else if (mBestTxChanIndex != mLastBestTxChanIndex) { + mTestPeriodSendCnt = 0; + mTestPeriodFailCnt = 0; + } + return mBestTxChanIndex; + } + + void addTxChanQuality (int8_t quality) + { + quality = mTxChanQuality[mBestTxChanIndex] + quality; + if (quality < RF_TX_CHAN_MIN_QUALITY) { + quality = RF_TX_CHAN_MIN_QUALITY; + } else if (quality > RF_TX_CHAN_MAX_QUALITY) { + quality = RF_TX_CHAN_MAX_QUALITY; + } + mTxChanQuality[mBestTxChanIndex] = quality; + } + + void evalTxChanQuality (bool crcPass, uint8_t Retransmits, uint8_t rxFragments, + uint8_t lastRxFragments) + { + if (!Retransmits || isNewTxChan ()) { + if (mTestPeriodSendCnt < 0xff) { + mTestPeriodSendCnt++; + } + } + if (lastRxFragments == rxFragments) { + // nothing received: send probably lost + if (!Retransmits || isNewTxChan()) { + if (mTestTxChanIndex == RF_TX_TEST_CHAN_1ST_USE) { + // we want _QUALITY_OK at least: switch back to orig quality + mTxChanQuality[mBestTxChanIndex] = mSaveOldTestChanQuality; + } + addTxChanQuality (RF_TX_CHAN_QUALITY_BAD); + if (mTestPeriodFailCnt < 0xff) { + mTestPeriodFailCnt++; + } + } // else: dont overestimate burst distortion + } else if (!lastRxFragments && crcPass) { + if (!Retransmits || isNewTxChan()) { + // every fragment received successfull immediately + addTxChanQuality (RF_TX_CHAN_QUALITY_GOOD); + } else { + // every fragment received successfully + addTxChanQuality (RF_TX_CHAN_QUALITY_OK); + } + } else if (crcPass) { + if (isNewTxChan ()) { + // last Fragment successfully received on new send channel + addTxChanQuality (RF_TX_CHAN_QUALITY_OK); + } + } else if (!Retransmits || isNewTxChan()) { + // no complete receive for this send channel + if (mTestTxChanIndex == RF_TX_TEST_CHAN_1ST_USE) { + // we want _QUALITY_OK at least: switch back to orig quality + mTxChanQuality[mBestTxChanIndex] = mSaveOldTestChanQuality; + } + addTxChanQuality (RF_TX_CHAN_QUALITY_LOW); + if (mTestPeriodFailCnt < 0xff) { + mTestPeriodFailCnt++; + } + } + if (mTestTxChanIndex == RF_TX_TEST_CHAN_1ST_USE) { + // special evaluation of test channel only at the beginning of current test period + mTestTxChanIndex = mBestTxChanIndex; + } + } + + void dumpTxChanQuality() + { + for(uint8_t i = 0; i < RF_CHANNELS; i++) { + DBGPRINT(" " + String (mTxChanQuality[i])); + } + DBGPRINT (", Cnt " + String (mTestPeriodSendCnt) + ", Fail " + String (mTestPeriodFailCnt)); + } + + void cleanupRxInfo() + { + // design: every day a new start + alarmCode = 0; + recordMeas.ts = 0; + recordInfo.ts = 0; + recordConfig.ts = 0; + recordAlarm.ts = 0; + } + private: void toRadioId(void) { DPRINTLN(DBG_VERBOSE, F("hmInverter.h:toRadioId")); diff --git a/src/hm/hmPayload.h b/src/hm/hmPayload.h index 64611192..b7c647d9 100644 --- a/src/hm/hmPayload.h +++ b/src/hm/hmPayload.h @@ -100,8 +100,6 @@ class HmPayload { iv->setValue(pos, rec, 0.0f); } } - iv->alarmCode = 0; // design: every day a new start - rec->ts = 0; // design: every day a new start notify(RealTimeRunData_Debug); } @@ -159,7 +157,8 @@ class HmPayload { DBGPRINT(F(" power limit ")); DBGPRINTLN(String(iv->powerLimit[0])); } - mSys->Radio.sendControlPacket(iv->radioId.u64, iv->devControlCmd, iv->powerLimit, false); + mSys->Radio.sendControlPacket(iv->radioId.u64, + iv->getNextTxChanIndex(), iv->devControlCmd, iv->powerLimit, false); mPayload[iv->id].txCmd = iv->devControlCmd; //iv->clearCmdQueue(); //iv->enqueCommand(SystemConfigPara); // read back power limit @@ -168,7 +167,8 @@ class HmPayload { DPRINT_IVID(DBG_INFO, iv->id); DBGPRINT(F("prepareDevInformCmd 0x")); DBGHEXLN(cmd); - mSys->Radio.prepareDevInformCmd(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex, false); + mSys->Radio.prepareDevInformCmd(iv->radioId.u64, + iv->getNextTxChanIndex(), cmd, mPayload[iv->id].ts, iv->alarmMesIndex, false); mPayload[iv->id].txCmd = cmd; } } @@ -252,8 +252,13 @@ class HmPayload { crcPass = build(iv->id, &pyldComplete, &Fragments); // evaluate quality of send channel with rcv params - mSys->Radio.evalSendChannelQuality (crcPass, mPayload[iv->id].retransmits, - Fragments, mPayload[iv->id].lastFragments); + if (retransmit) { + iv->evalTxChanQuality (crcPass, mPayload[iv->id].retransmits, + Fragments, mPayload[iv->id].lastFragments); + DPRINT (DBG_INFO, "Quality: "); + iv->dumpTxChanQuality(); + DBGPRINTLN(""); + } mPayload[iv->id].lastFragments = Fragments; if (!crcPass && !pyldComplete) { // payload not complete if ((mPayload[iv->id].requested) && (retransmit)) { @@ -266,7 +271,8 @@ class HmPayload { } else if(iv->devControlCmd == ActivePowerContr) { DPRINT_IVID(DBG_INFO, iv->id); DPRINTLN(DBG_INFO, F("retransmit power limit")); - mSys->Radio.sendControlPacket(iv->radioId.u64, iv->devControlCmd, iv->powerLimit, true); + mSys->Radio.sendControlPacket(iv->radioId.u64, + iv->getNextTxChanIndex(), iv->devControlCmd, iv->powerLimit, true); } else { if(false == mPayload[iv->id].gotFragment) { DPRINT_IVID(DBG_WARN, iv->id); @@ -277,7 +283,9 @@ class HmPayload { DBGPRINTLN(F("nothing received: complete retransmit")); mPayload[iv->id].txCmd = iv->getQueuedCmd(); DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") prepareDevInformCmd 0x") + String(mPayload[iv->id].txCmd, HEX)); - mSys->Radio.prepareDevInformCmd(iv->radioId.u64, mPayload[iv->id].txCmd, mPayload[iv->id].ts, iv->alarmMesIndex, true); + + mSys->Radio.prepareDevInformCmd(iv->radioId.u64, + iv->getNextTxChanIndex(), mPayload[iv->id].txCmd, mPayload[iv->id].ts, iv->alarmMesIndex, true); } } else { for (uint8_t i = 0; i < (mPayload[iv->id].maxPackId - 1); i++) { @@ -286,7 +294,8 @@ class HmPayload { DBGPRINT(F("Frame ")); DBGPRINT(String(i + 1)); DBGPRINTLN(F(" missing: Request Retransmit")); - mSys->Radio.sendCmdPacket(iv->radioId.u64, TX_REQ_INFO, (SINGLE_FRAME + i), true); + mSys->Radio.sendCmdPacket(iv->radioId.u64, + iv->getNextTxChanIndex (), TX_REQ_INFO, (SINGLE_FRAME + i), true); break; // only request retransmit one frame per loop } yield(); @@ -306,7 +315,8 @@ class HmPayload { DPRINT_IVID(DBG_INFO, iv->id); DBGPRINT(F("prepareDevInformCmd 0x")); DBGHEXLN(mPayload[iv->id].txCmd); - mSys->Radio.prepareDevInformCmd(iv->radioId.u64, mPayload[iv->id].txCmd, mPayload[iv->id].ts, iv->alarmMesIndex, true); + mSys->Radio.prepareDevInformCmd(iv->radioId.u64, + iv->getNextTxChanIndex (), mPayload[iv->id].txCmd, mPayload[iv->id].ts, iv->alarmMesIndex, true); } else if (false == mPayload[iv->id].gotFragment) { // only if there is no sign of life mPayload[iv->id].rxTmo = true; // inv might be down, no complete retransmit anymore diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h index a4870fe7..798fa1c6 100644 --- a/src/hm/hmRadio.h +++ b/src/hm/hmRadio.h @@ -14,20 +14,11 @@ #define SPI_SPEED 1000000 -#define RF_CHANNELS 5 - #define TX_REQ_INFO 0x15 #define TX_REQ_DEVCONTROL 0x51 #define ALL_FRAMES 0x80 #define SINGLE_FRAME 0x81 -#define SEND_CHANNEL_MAX_QUALITY 4 -#define SEND_CHANNEL_MIN_QUALITY -6 -#define SEND_CHANNEL_QUALITY_GOOD 2 -#define SEND_CHANNEL_QUALITY_OK 1 -#define SEND_CHANNEL_QUALITY_NEUTRAL 0 -#define SEND_CHANNEL_QUALITY_LOW -1 -#define SEND_CHANNEL_QUALITY_BAD -2 const char* const rf24AmpPowerNames[] = {"MIN", "LOW", "HIGH", "MAX"}; @@ -79,8 +70,8 @@ class HmRadio { mRfChLst[4] = 75; // default channels - mTxChIdx = 2; // Start TX with 40 - mRxChIdx = 0; // Start RX with 03 + mTxChIdx = AHOY_RF24_DEF_TX_CHANNEL; + mRxChIdx = AHOY_RF24_DEF_RX_CHANNEL; mSendCnt = 0; mRetransmits = 0; @@ -198,7 +189,7 @@ class HmRadio { mSerialDebug = true; } - void sendControlPacket(uint64_t invId, uint8_t cmd, uint16_t *data, bool isRetransmit, bool isNoMI = true) { + void sendControlPacket(uint64_t invId, uint8_t rf_ch, uint8_t cmd, uint16_t *data, bool isRetransmit, bool isNoMI = true) { DPRINT(DBG_INFO, F("sendControlPacket cmd: 0x")); DBGHEXLN(cmd); initPacket(invId, TX_REQ_DEVCONTROL, SINGLE_FRAME); @@ -234,10 +225,10 @@ class HmRadio { } cnt++; } - sendPacket(invId, cnt, isRetransmit, isNoMI); + sendPacket(invId, rf_ch, cnt, isRetransmit, isNoMI); } - void prepareDevInformCmd(uint64_t invId, uint8_t cmd, uint32_t ts, uint16_t alarmMesId, bool isRetransmit, uint8_t reqfld=TX_REQ_INFO) { // might not be necessary to add additional arg. + void prepareDevInformCmd(uint64_t invId, uint8_t rf_ch, uint8_t cmd, uint32_t ts, uint16_t alarmMesId, bool isRetransmit, uint8_t reqfld=TX_REQ_INFO) { // might not be necessary to add additional arg. if(mSerialDebug) { DPRINT(DBG_DEBUG, F("prepareDevInformCmd 0x")); DPRINTLN(DBG_DEBUG,String(cmd, HEX)); @@ -255,12 +246,12 @@ class HmRadio { mTxBuf[18] = (alarmMesId >> 8) & 0xff; mTxBuf[19] = (alarmMesId ) & 0xff; } - sendPacket(invId, 24, isRetransmit, true); + sendPacket(invId, rf_ch, 24, isRetransmit, true); } - void sendCmdPacket(uint64_t invId, uint8_t mid, uint8_t pid, bool isRetransmit, bool appendCrc16=true) { + void sendCmdPacket(uint64_t invId, uint8_t rf_ch, uint8_t mid, uint8_t pid, bool isRetransmit, bool appendCrc16=true) { initPacket(invId, mid, pid); - sendPacket(invId, 10, isRetransmit, appendCrc16); + sendPacket(invId, rf_ch, 10, isRetransmit, appendCrc16); } void dumpBuf(uint8_t buf[], uint8_t len) { @@ -282,81 +273,6 @@ class HmRadio { return mNrf24.isPVariant(); } - bool isNewSendChannel () - { - return mTxChIdx != mTxLastChIdx; - } - - uint8_t getNextSendChannelIndex (void) - { - // start with the next index: round robbin in case of same max bad quality for all channels - uint8_t bestIndex = (mTxChIdx + 1) % RF_CHANNELS; - uint8_t curIndex = (bestIndex + 1) % RF_CHANNELS; - uint16_t i; - - for (i=1; i mChQuality[bestIndex]) { - bestIndex = curIndex; - } - curIndex = (curIndex + 1) % RF_CHANNELS; - } - return bestIndex; - } - - void addSendChannelQuality (int8_t quality) - { - // assume: mTxChIdx is still the last send channel index used - quality = mChQuality[mTxChIdx] + quality; - if (quality < SEND_CHANNEL_MIN_QUALITY) { - quality = SEND_CHANNEL_MIN_QUALITY; - } else if (quality > SEND_CHANNEL_MAX_QUALITY) { - quality = SEND_CHANNEL_MAX_QUALITY; - } - mChQuality[mTxChIdx] = quality; - } - - void evalSendChannelQuality (bool crcPass, uint8_t Retransmits, uint8_t rxFragments, - uint8_t lastRxFragments) - { - if (lastRxFragments == rxFragments) { - // nothing received: send probably lost - if (!Retransmits || isNewSendChannel()) { - // dont overestimate burst distortion - addSendChannelQuality (SEND_CHANNEL_QUALITY_BAD); - } - } else if (!lastRxFragments && crcPass) { - if (!Retransmits || isNewSendChannel()) { - // every fragment received successfull immediately - addSendChannelQuality (SEND_CHANNEL_QUALITY_GOOD); - } else { - // every fragment received successfully - addSendChannelQuality (SEND_CHANNEL_QUALITY_OK); - } - } else if (crcPass) { - if (isNewSendChannel ()) { - // last Fragment successfully received on new send channel - addSendChannelQuality (SEND_CHANNEL_QUALITY_OK); - } - } else if (!Retransmits || isNewSendChannel()) { - // no complete receive for this send channel - addSendChannelQuality (SEND_CHANNEL_QUALITY_LOW); - } - } - - void resetSendChannelQuality () - { - for(uint8_t i = 0; i < RF_CHANNELS; i++) { - mChQuality[mTxChIdx] = 0; - } - } - - void dumpSendQuality() - { - for(uint8_t i = 0; i < RF_CHANNELS; i++) { - DBGPRINT(" " + String (mChQuality[i])); - } - } - std::queue mBufCtrl; uint32_t mSendCnt; @@ -409,7 +325,7 @@ class HmRadio { mTxBuf[9] = pid; } - void sendPacket(uint64_t invId, uint8_t len, bool isRetransmit, bool appendCrc16=true) { + void sendPacket(uint64_t invId, uint8_t rf_ch, uint8_t len, bool isRetransmit, bool appendCrc16=true) { //DPRINTLN(DBG_VERBOSE, F("hmRadio.h:sendPacket")); //DPRINTLN(DBG_VERBOSE, "sent packet: #" + String(mSendCnt)); @@ -426,8 +342,7 @@ class HmRadio { // set TX and RX channels - mTxLastChIdx = mTxChIdx; - mTxChIdx = getNextSendChannelIndex (); + mTxChIdx = rf_ch; mRxChIdx = (mTxChIdx + 2) % RF_CHANNELS; if(mSerialDebug) { @@ -439,10 +354,8 @@ class HmRadio { DBGPRINT(F(" | ")); dumpBuf(mTxBuf, len); #else - DPRINT(DBG_INFO, F("TX (Ch ") + String (mRfChLst[mTxChIdx]) + "), " + - String (len) + " Bytes, Quality:"); - dumpSendQuality(); - DBGPRINTLN(""); + DPRINTLN(DBG_INFO, F("TX (Ch ") + String (mRfChLst[mTxChIdx]) + "), " + + String (len) + " Bytes"); #endif } mNrf24.stopListening(); @@ -460,14 +373,13 @@ class HmRadio { uint64_t DTU_RADIO_ID; uint8_t mRfChLst[RF_CHANNELS]; - int8_t mChQuality[RF_CHANNELS]; - uint8_t mTxChIdx; - uint8_t mTxLastChIdx; - uint8_t mRxChIdx; SPIClass* mSpi; RF24 mNrf24; uint8_t mTxBuf[MAX_RF_PAYLOAD_SIZE]; + uint8_t mTxChIdx; + uint8_t mRxChIdx; + }; #endif /*__RADIO_H__*/ diff --git a/src/hm/miPayload.h b/src/hm/miPayload.h index b6e3ecca..2ee669b0 100644 --- a/src/hm/miPayload.h +++ b/src/hm/miPayload.h @@ -26,6 +26,8 @@ typedef struct { uint8_t invId; uint8_t retransmits; bool gotFragment; + uint8_t fragments; + uint8_t lastFragments; /* uint8_t data[MAX_PAYLOAD_ENTRIES][MAX_RF_PAYLOAD_SIZE]; uint8_t maxPackId; @@ -124,7 +126,8 @@ class MiPayload { DBGPRINT(F(" power limit ")); DBGPRINTLN(String(iv->powerLimit[0])); } - mSys->Radio.sendControlPacket(iv->radioId.u64, iv->devControlCmd, iv->powerLimit, false, false); + mSys->Radio.sendControlPacket(iv->radioId.u64, + iv->getNextTxChanIndex(), iv->devControlCmd, iv->powerLimit, false, false); mPayload[iv->id].txCmd = iv->devControlCmd; mPayload[iv->id].limitrequested = true; @@ -148,10 +151,12 @@ class MiPayload { if (cmd == 0x01 || cmd == SystemConfigPara ) { //0x1 and 0x05 for HM-types cmd = 0x0f; // for MI, these seem to make part of the Polling the device software and hardware version number command cmd2 = cmd == SystemConfigPara ? 0x01 : 0x00; //perhaps we can only try to get second frame? - mSys->Radio.sendCmdPacket(iv->radioId.u64, cmd, cmd2, false, false); + mSys->Radio.sendCmdPacket(iv->radioId.u64, + iv->getNextTxChanIndex(), cmd, cmd2, false, false); } else { //mSys->Radio.prepareDevInformCmd(iv->radioId.u64, cmd2, mPayload[iv->id].ts, iv->alarmMesIndex, false, cmd); - mSys->Radio.sendCmdPacket(iv->radioId.u64, cmd, cmd2, false, false); + mSys->Radio.sendCmdPacket(iv->radioId.u64, + iv->getNextTxChanIndex(), cmd, cmd2, false, false); }; mPayload[iv->id].txCmd = cmd; @@ -192,6 +197,8 @@ class MiPayload { record_t<> *rec = iv->getRecordStruct(InverterDevInform_All); // choose the record structure rec->ts = mPayload[iv->id].ts; mPayload[iv->id].gotFragment = true; + mPayload[iv->id].fragments++; + /* Polling the device software and hardware version number command @@ -234,6 +241,7 @@ const byteAssign_t InfoAssignment[] = { } iv->isConnected = true; mPayload[iv->id].gotFragment = true; + mPayload[iv->id].fragments++; if(mSerialDebug) { DPRINT_IVID(DBG_INFO, iv->id); DPRINT(DBG_INFO,F("HW_VER is ")); @@ -246,6 +254,7 @@ const byteAssign_t InfoAssignment[] = { DPRINT(DBG_INFO,F("HW_PartNo ")); DBGPRINTLN(String((uint32_t) (((p->packet[10] << 8) | p->packet[11]) << 8 | p->packet[12]) << 8 | p->packet[13])); mPayload[iv->id].gotFragment = true; + mPayload[iv->id].fragments++; iv->setValue(iv->getPosByChFld(0, FLD_YT, rec), rec, (float) ((p->packet[20] << 8) + p->packet[21])/1); if(mSerialDebug) { DPRINT(DBG_INFO,F("HW_FB_TLmValue ")); @@ -266,6 +275,7 @@ const byteAssign_t InfoAssignment[] = { DBGPRINTLN(F("got 3rd frame (hw info)")); iv->setQueuedCmdFinished(); mPayload[iv->id].complete = true; + mPayload[iv->id].fragments++; mStat->rxSuccess++; } @@ -423,6 +433,17 @@ const byteAssign_t InfoAssignment[] = { //DPRINTLN(DBG_INFO, F("Pyld incompl code")); //info for testing only bool crcPass, pyldComplete; crcPass = build(iv->id, &pyldComplete); + + // evaluate quality of send channel with rcv params + if (retransmit) { + iv->evalTxChanQuality (crcPass, mPayload[iv->id].retransmits, + mPayload[iv->id].fragments, mPayload[iv->id].lastFragments); + DPRINT (DBG_INFO, "Quality: "); + iv->dumpTxChanQuality(); + DBGPRINTLN(""); + } + + mPayload[iv->id].lastFragments = mPayload[iv->id].fragments; if (!crcPass && !pyldComplete) { // payload not complete if ((mPayload[iv->id].requested) && (retransmit)) { if (iv->devControlCmd == Restart || iv->devControlCmd == CleanState_LockAndAlarm) { @@ -433,7 +454,8 @@ const byteAssign_t InfoAssignment[] = { } else if(iv->devControlCmd == ActivePowerContr) { DPRINT_IVID(DBG_INFO, iv->id); DBGPRINTLN(F("retransmit power limit")); - mSys->Radio.sendControlPacket(iv->radioId.u64, iv->devControlCmd, iv->powerLimit, true, false); + mSys->Radio.sendControlPacket(iv->radioId.u64, + iv->getNextTxChanIndex(), iv->devControlCmd, iv->powerLimit, true, false); } else { uint8_t cmd = mPayload[iv->id].txCmd; if (mPayload[iv->id].retransmits < mMaxRetrans) { @@ -444,7 +466,8 @@ const byteAssign_t InfoAssignment[] = { mPayload[iv->id].retransmits = mMaxRetrans; } else if ( cmd == 0x0f ) { //hard/firmware request - mSys->Radio.sendCmdPacket(iv->radioId.u64, 0x0f, 0x00, true, false); + mSys->Radio.sendCmdPacket(iv->radioId.u64, + iv->getNextTxChanIndex(), 0x0f, 0x00, true, false); //iv->setQueuedCmdFinished(); //cmd = iv->getQueuedCmd(); } else { @@ -481,7 +504,8 @@ const byteAssign_t InfoAssignment[] = { } DBGPRINT(F(" 0x")); DBGHEXLN(cmd); - mSys->Radio.sendCmdPacket(iv->radioId.u64, cmd, cmd, true, false); + mSys->Radio.sendCmdPacket(iv->radioId.u64, + iv->getNextTxChanIndex(), cmd, cmd, true, false); //mSys->Radio.prepareDevInformCmd(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex, true, cmd); yield(); } @@ -499,7 +523,8 @@ const byteAssign_t InfoAssignment[] = { DBGPRINT(F("prepareDevInformCmd 0x")); DBGHEXLN(mPayload[iv->id].txCmd); //mSys->Radio.prepareDevInformCmd(iv->radioId.u64, mPayload[iv->id].txCmd, mPayload[iv->id].ts, iv->alarmMesIndex, true); - mSys->Radio.sendCmdPacket(iv->radioId.u64, mPayload[iv->id].txCmd, mPayload[iv->id].txCmd, false, false); + mSys->Radio.sendCmdPacket(iv->radioId.u64, + iv->getNextTxChanIndex(), mPayload[iv->id].txCmd, mPayload[iv->id].txCmd, false, false); } } /*else { // payload complete @@ -568,6 +593,7 @@ const byteAssign_t InfoAssignment[] = { record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); // choose the record structure rec->ts = mPayload[iv->id].ts; mPayload[iv->id].gotFragment = true; + mPayload[iv->id].fragments++; mPayload[iv->id].txId = p->packet[0]; miStsConsolidate(iv, stschan, rec, p->packet[10], p->packet[12], p->packet[9], p->packet[11]); mPayload[iv->id].stsAB[stschan] = true; @@ -639,6 +665,7 @@ const byteAssign_t InfoAssignment[] = { record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); // choose the parser rec->ts = mPayload[iv->id].ts; mPayload[iv->id].gotFragment = true; + mPayload[iv->id].fragments++; uint8_t datachan = ( p->packet[0] == 0x89 || p->packet[0] == (0x36 + ALL_FRAMES) ) ? CH1 : ( p->packet[0] == 0x91 || p->packet[0] == (0x37 + ALL_FRAMES) ) ? CH2 : @@ -685,7 +712,8 @@ const byteAssign_t InfoAssignment[] = { if (p->packet[0] < (0x39 + ALL_FRAMES) ) { /*uint8_t cmd = p->packet[0] - ALL_FRAMES + 1; - mSys->Radio.prepareDevInformCmd(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex, false, cmd); + mSys->Radio.prepareDevInformCmd(iv->radioId.u64, + iv->getNextTxChanIndex(), cmd, mPayload[iv->id].ts, iv->alarmMesIndex, false, cmd); mPayload[iv->id].txCmd = cmd;*/ mPayload[iv->id].txCmd++; mPayload[iv->id].retransmits = 0; // reserve retransmissions for each response @@ -765,7 +793,7 @@ const byteAssign_t InfoAssignment[] = { uint8_t txCmd = mPayload[id].txCmd; if(!*complete) { - DPRINTLN(DBG_VERBOSE, F("incomlete, txCmd is 0x") + String(txCmd, HEX)); + DPRINTLN(DBG_VERBOSE, F("incomplete, txCmd is 0x") + String(txCmd, HEX)); //DBGHEXLN(txCmd); if (txCmd == 0x09 || txCmd == 0x11 || (txCmd >= 0x36 && txCmd <= 0x39)) return false; @@ -800,6 +828,8 @@ const byteAssign_t InfoAssignment[] = { DBGPRINTLN(F("resetPayload")); memset(mPayload[id].len, 0, MAX_PAYLOAD_ENTRIES); mPayload[id].gotFragment = false; + mPayload[id].fragments = 0; + mPayload[id].lastFragments = 0; /*mPayload[id].maxPackId = MAX_PAYLOAD_ENTRIES; mPayload[id].lastFound = false;*/ mPayload[id].retransmits = 0;