Browse Source

Send Channel evaluation is now part of inverter. Additional test period to find best send channel.

pull/1080/head
no name 2 years ago
parent
commit
0ec95f83f0
  1. 9
      src/app.cpp
  2. 3
      src/hm/hmDefines.h
  3. 146
      src/hm/hmInverter.h
  4. 30
      src/hm/hmPayload.h
  5. 118
      src/hm/hmRadio.h
  6. 48
      src/hm/miPayload.h

9
src/app.cpp

@ -346,13 +346,14 @@ void app::tickMinute(void) {
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void app::tickMidnight(void) { void app::tickMidnight(void) {
Inverter<> *iv;
if (mConfig->inst.rstYieldMidNight) { if (mConfig->inst.rstYieldMidNight) {
// only if 'reset values at midnight is enabled' // only if 'reset values at midnight is enabled'
uint32_t localTime = gTimezone.toLocal(mTimestamp); uint32_t localTime = gTimezone.toLocal(mTimestamp);
uint32_t nxtTrig = gTimezone.toUTC(localTime - (localTime % 86400) + 86400); // next midnight local time uint32_t nxtTrig = gTimezone.toUTC(localTime - (localTime % 86400) + 86400); // next midnight local time
onceAt(std::bind(&app::tickMidnight, this), nxtTrig, "mid2"); onceAt(std::bind(&app::tickMidnight, this), nxtTrig, "mid2");
Inverter<> *iv;
// set values to zero, except yield total // set values to zero, except yield total
for (uint8_t id = 0; id < mSys.getNumInverters(); id++) { for (uint8_t id = 0; id < mSys.getNumInverters(); id++) {
iv = mSys.getInverterByPos(id); iv = mSys.getInverterByPos(id);
@ -367,7 +368,11 @@ void app::tickMidnight(void) {
mMqtt.tickerMidnight(); mMqtt.tickerMidnight();
#endif #endif
} }
mSys.Radio.resetSendChannelQuality(); for (uint8_t id = 0; id < mSys.getNumInverters(); id++) {
if ((iv = mSys.getInverterByPos(id))) {
iv->cleanupRxInfo();
}
}
mSys.cleanup_history(); mSys.cleanup_history();
#ifdef AHOY_SML_OBIS_SUPPORT #ifdef AHOY_SML_OBIS_SUPPORT
// design: allways try to clean up // design: allways try to clean up

3
src/hm/hmDefines.h

@ -9,6 +9,9 @@
#include "../utils/dbg.h" #include "../utils/dbg.h"
#include <cstdint> #include <cstdint>
#define RF_CHANNELS 5
#define AHOY_RF24_DEF_TX_CHANNEL 2 // 40
#define AHOY_RF24_DEF_RX_CHANNEL 0 // 3
// inverter generations // inverter generations
enum {IV_HM = 0, IV_MI}; enum {IV_HM = 0, IV_MI};

146
src/hm/hmInverter.h

@ -16,6 +16,21 @@
#include <queue> #include <queue>
#include "../config/settings.h" #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 * For values which are of interest and not transmitted by the inverter can be
* calculated automatically. * calculated automatically.
@ -134,6 +149,13 @@ class Inverter {
uint16_t alarmCode; // last Alarm uint16_t alarmCode; // last Alarm
uint32_t alarmStart; uint32_t alarmStart;
uint32_t alarmEnd; 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() { Inverter() {
ivGen = IV_HM; ivGen = IV_HM;
@ -146,6 +168,8 @@ class Inverter {
alarmMesIndex = 0; alarmMesIndex = 0;
isConnected = false; isConnected = false;
alarmCode = 0; alarmCode = 0;
mBestTxChanIndex = AHOY_RF24_DEF_TX_CHANNEL ? AHOY_RF24_DEF_TX_CHANNEL - 1 : RF_CHANNELS - 1;
mLastBestTxChanIndex = AHOY_RF24_DEF_TX_CHANNEL;
} }
~Inverter() { ~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<RF_CHANNELS; i++) {
if (mTxChanQuality[curIndex] > 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: private:
void toRadioId(void) { void toRadioId(void) {
DPRINTLN(DBG_VERBOSE, F("hmInverter.h:toRadioId")); DPRINTLN(DBG_VERBOSE, F("hmInverter.h:toRadioId"));

30
src/hm/hmPayload.h

@ -100,8 +100,6 @@ class HmPayload {
iv->setValue(pos, rec, 0.0f); 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); notify(RealTimeRunData_Debug);
} }
@ -159,7 +157,8 @@ class HmPayload {
DBGPRINT(F(" power limit ")); DBGPRINT(F(" power limit "));
DBGPRINTLN(String(iv->powerLimit[0])); 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; mPayload[iv->id].txCmd = iv->devControlCmd;
//iv->clearCmdQueue(); //iv->clearCmdQueue();
//iv->enqueCommand<InfoCommand>(SystemConfigPara); // read back power limit //iv->enqueCommand<InfoCommand>(SystemConfigPara); // read back power limit
@ -168,7 +167,8 @@ class HmPayload {
DPRINT_IVID(DBG_INFO, iv->id); DPRINT_IVID(DBG_INFO, iv->id);
DBGPRINT(F("prepareDevInformCmd 0x")); DBGPRINT(F("prepareDevInformCmd 0x"));
DBGHEXLN(cmd); 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; mPayload[iv->id].txCmd = cmd;
} }
} }
@ -252,8 +252,13 @@ class HmPayload {
crcPass = build(iv->id, &pyldComplete, &Fragments); crcPass = build(iv->id, &pyldComplete, &Fragments);
// evaluate quality of send channel with rcv params // evaluate quality of send channel with rcv params
mSys->Radio.evalSendChannelQuality (crcPass, mPayload[iv->id].retransmits, if (retransmit) {
Fragments, mPayload[iv->id].lastFragments); iv->evalTxChanQuality (crcPass, mPayload[iv->id].retransmits,
Fragments, mPayload[iv->id].lastFragments);
DPRINT (DBG_INFO, "Quality: ");
iv->dumpTxChanQuality();
DBGPRINTLN("");
}
mPayload[iv->id].lastFragments = Fragments; mPayload[iv->id].lastFragments = Fragments;
if (!crcPass && !pyldComplete) { // payload not complete if (!crcPass && !pyldComplete) { // payload not complete
if ((mPayload[iv->id].requested) && (retransmit)) { if ((mPayload[iv->id].requested) && (retransmit)) {
@ -266,7 +271,8 @@ class HmPayload {
} else if(iv->devControlCmd == ActivePowerContr) { } else if(iv->devControlCmd == ActivePowerContr) {
DPRINT_IVID(DBG_INFO, iv->id); DPRINT_IVID(DBG_INFO, iv->id);
DPRINTLN(DBG_INFO, F("retransmit power limit")); 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 { } else {
if(false == mPayload[iv->id].gotFragment) { if(false == mPayload[iv->id].gotFragment) {
DPRINT_IVID(DBG_WARN, iv->id); DPRINT_IVID(DBG_WARN, iv->id);
@ -277,7 +283,9 @@ class HmPayload {
DBGPRINTLN(F("nothing received: complete retransmit")); DBGPRINTLN(F("nothing received: complete retransmit"));
mPayload[iv->id].txCmd = iv->getQueuedCmd(); mPayload[iv->id].txCmd = iv->getQueuedCmd();
DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") prepareDevInformCmd 0x") + String(mPayload[iv->id].txCmd, HEX)); 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 { } else {
for (uint8_t i = 0; i < (mPayload[iv->id].maxPackId - 1); i++) { for (uint8_t i = 0; i < (mPayload[iv->id].maxPackId - 1); i++) {
@ -286,7 +294,8 @@ class HmPayload {
DBGPRINT(F("Frame ")); DBGPRINT(F("Frame "));
DBGPRINT(String(i + 1)); DBGPRINT(String(i + 1));
DBGPRINTLN(F(" missing: Request Retransmit")); 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 break; // only request retransmit one frame per loop
} }
yield(); yield();
@ -306,7 +315,8 @@ class HmPayload {
DPRINT_IVID(DBG_INFO, iv->id); DPRINT_IVID(DBG_INFO, iv->id);
DBGPRINT(F("prepareDevInformCmd 0x")); DBGPRINT(F("prepareDevInformCmd 0x"));
DBGHEXLN(mPayload[iv->id].txCmd); 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) { } else if (false == mPayload[iv->id].gotFragment) {
// only if there is no sign of life // only if there is no sign of life
mPayload[iv->id].rxTmo = true; // inv might be down, no complete retransmit anymore mPayload[iv->id].rxTmo = true; // inv might be down, no complete retransmit anymore

118
src/hm/hmRadio.h

@ -14,20 +14,11 @@
#define SPI_SPEED 1000000 #define SPI_SPEED 1000000
#define RF_CHANNELS 5
#define TX_REQ_INFO 0x15 #define TX_REQ_INFO 0x15
#define TX_REQ_DEVCONTROL 0x51 #define TX_REQ_DEVCONTROL 0x51
#define ALL_FRAMES 0x80 #define ALL_FRAMES 0x80
#define SINGLE_FRAME 0x81 #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"}; const char* const rf24AmpPowerNames[] = {"MIN", "LOW", "HIGH", "MAX"};
@ -79,8 +70,8 @@ class HmRadio {
mRfChLst[4] = 75; mRfChLst[4] = 75;
// default channels // default channels
mTxChIdx = 2; // Start TX with 40 mTxChIdx = AHOY_RF24_DEF_TX_CHANNEL;
mRxChIdx = 0; // Start RX with 03 mRxChIdx = AHOY_RF24_DEF_RX_CHANNEL;
mSendCnt = 0; mSendCnt = 0;
mRetransmits = 0; mRetransmits = 0;
@ -198,7 +189,7 @@ class HmRadio {
mSerialDebug = true; 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")); DPRINT(DBG_INFO, F("sendControlPacket cmd: 0x"));
DBGHEXLN(cmd); DBGHEXLN(cmd);
initPacket(invId, TX_REQ_DEVCONTROL, SINGLE_FRAME); initPacket(invId, TX_REQ_DEVCONTROL, SINGLE_FRAME);
@ -234,10 +225,10 @@ class HmRadio {
} }
cnt++; 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) { if(mSerialDebug) {
DPRINT(DBG_DEBUG, F("prepareDevInformCmd 0x")); DPRINT(DBG_DEBUG, F("prepareDevInformCmd 0x"));
DPRINTLN(DBG_DEBUG,String(cmd, HEX)); DPRINTLN(DBG_DEBUG,String(cmd, HEX));
@ -255,12 +246,12 @@ class HmRadio {
mTxBuf[18] = (alarmMesId >> 8) & 0xff; mTxBuf[18] = (alarmMesId >> 8) & 0xff;
mTxBuf[19] = (alarmMesId ) & 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); initPacket(invId, mid, pid);
sendPacket(invId, 10, isRetransmit, appendCrc16); sendPacket(invId, rf_ch, 10, isRetransmit, appendCrc16);
} }
void dumpBuf(uint8_t buf[], uint8_t len) { void dumpBuf(uint8_t buf[], uint8_t len) {
@ -282,81 +273,6 @@ class HmRadio {
return mNrf24.isPVariant(); 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<RF_CHANNELS; i++) {
if (mChQuality[curIndex] > 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<packet_t> mBufCtrl; std::queue<packet_t> mBufCtrl;
uint32_t mSendCnt; uint32_t mSendCnt;
@ -409,7 +325,7 @@ class HmRadio {
mTxBuf[9] = pid; 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, F("hmRadio.h:sendPacket"));
//DPRINTLN(DBG_VERBOSE, "sent packet: #" + String(mSendCnt)); //DPRINTLN(DBG_VERBOSE, "sent packet: #" + String(mSendCnt));
@ -426,8 +342,7 @@ class HmRadio {
// set TX and RX channels // set TX and RX channels
mTxLastChIdx = mTxChIdx; mTxChIdx = rf_ch;
mTxChIdx = getNextSendChannelIndex ();
mRxChIdx = (mTxChIdx + 2) % RF_CHANNELS; mRxChIdx = (mTxChIdx + 2) % RF_CHANNELS;
if(mSerialDebug) { if(mSerialDebug) {
@ -439,10 +354,8 @@ class HmRadio {
DBGPRINT(F(" | ")); DBGPRINT(F(" | "));
dumpBuf(mTxBuf, len); dumpBuf(mTxBuf, len);
#else #else
DPRINT(DBG_INFO, F("TX (Ch ") + String (mRfChLst[mTxChIdx]) + "), " + DPRINTLN(DBG_INFO, F("TX (Ch ") + String (mRfChLst[mTxChIdx]) + "), " +
String (len) + " Bytes, Quality:"); String (len) + " Bytes");
dumpSendQuality();
DBGPRINTLN("");
#endif #endif
} }
mNrf24.stopListening(); mNrf24.stopListening();
@ -460,14 +373,13 @@ class HmRadio {
uint64_t DTU_RADIO_ID; uint64_t DTU_RADIO_ID;
uint8_t mRfChLst[RF_CHANNELS]; uint8_t mRfChLst[RF_CHANNELS];
int8_t mChQuality[RF_CHANNELS];
uint8_t mTxChIdx;
uint8_t mTxLastChIdx;
uint8_t mRxChIdx;
SPIClass* mSpi; SPIClass* mSpi;
RF24 mNrf24; RF24 mNrf24;
uint8_t mTxBuf[MAX_RF_PAYLOAD_SIZE]; uint8_t mTxBuf[MAX_RF_PAYLOAD_SIZE];
uint8_t mTxChIdx;
uint8_t mRxChIdx;
}; };
#endif /*__RADIO_H__*/ #endif /*__RADIO_H__*/

48
src/hm/miPayload.h

@ -26,6 +26,8 @@ typedef struct {
uint8_t invId; uint8_t invId;
uint8_t retransmits; uint8_t retransmits;
bool gotFragment; bool gotFragment;
uint8_t fragments;
uint8_t lastFragments;
/* /*
uint8_t data[MAX_PAYLOAD_ENTRIES][MAX_RF_PAYLOAD_SIZE]; uint8_t data[MAX_PAYLOAD_ENTRIES][MAX_RF_PAYLOAD_SIZE];
uint8_t maxPackId; uint8_t maxPackId;
@ -124,7 +126,8 @@ class MiPayload {
DBGPRINT(F(" power limit ")); DBGPRINT(F(" power limit "));
DBGPRINTLN(String(iv->powerLimit[0])); 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].txCmd = iv->devControlCmd;
mPayload[iv->id].limitrequested = true; mPayload[iv->id].limitrequested = true;
@ -148,10 +151,12 @@ class MiPayload {
if (cmd == 0x01 || cmd == SystemConfigPara ) { //0x1 and 0x05 for HM-types 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 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? 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 { } else {
//mSys->Radio.prepareDevInformCmd(iv->radioId.u64, cmd2, mPayload[iv->id].ts, iv->alarmMesIndex, false, cmd); //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; mPayload[iv->id].txCmd = cmd;
@ -192,6 +197,8 @@ class MiPayload {
record_t<> *rec = iv->getRecordStruct(InverterDevInform_All); // choose the record structure record_t<> *rec = iv->getRecordStruct(InverterDevInform_All); // choose the record structure
rec->ts = mPayload[iv->id].ts; rec->ts = mPayload[iv->id].ts;
mPayload[iv->id].gotFragment = true; mPayload[iv->id].gotFragment = true;
mPayload[iv->id].fragments++;
/* /*
Polling the device software and hardware version number command Polling the device software and hardware version number command
@ -234,6 +241,7 @@ const byteAssign_t InfoAssignment[] = {
} }
iv->isConnected = true; iv->isConnected = true;
mPayload[iv->id].gotFragment = true; mPayload[iv->id].gotFragment = true;
mPayload[iv->id].fragments++;
if(mSerialDebug) { if(mSerialDebug) {
DPRINT_IVID(DBG_INFO, iv->id); DPRINT_IVID(DBG_INFO, iv->id);
DPRINT(DBG_INFO,F("HW_VER is ")); DPRINT(DBG_INFO,F("HW_VER is "));
@ -246,6 +254,7 @@ const byteAssign_t InfoAssignment[] = {
DPRINT(DBG_INFO,F("HW_PartNo ")); 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])); 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].gotFragment = true;
mPayload[iv->id].fragments++;
iv->setValue(iv->getPosByChFld(0, FLD_YT, rec), rec, (float) ((p->packet[20] << 8) + p->packet[21])/1); iv->setValue(iv->getPosByChFld(0, FLD_YT, rec), rec, (float) ((p->packet[20] << 8) + p->packet[21])/1);
if(mSerialDebug) { if(mSerialDebug) {
DPRINT(DBG_INFO,F("HW_FB_TLmValue ")); DPRINT(DBG_INFO,F("HW_FB_TLmValue "));
@ -266,6 +275,7 @@ const byteAssign_t InfoAssignment[] = {
DBGPRINTLN(F("got 3rd frame (hw info)")); DBGPRINTLN(F("got 3rd frame (hw info)"));
iv->setQueuedCmdFinished(); iv->setQueuedCmdFinished();
mPayload[iv->id].complete = true; mPayload[iv->id].complete = true;
mPayload[iv->id].fragments++;
mStat->rxSuccess++; mStat->rxSuccess++;
} }
@ -423,6 +433,17 @@ const byteAssign_t InfoAssignment[] = {
//DPRINTLN(DBG_INFO, F("Pyld incompl code")); //info for testing only //DPRINTLN(DBG_INFO, F("Pyld incompl code")); //info for testing only
bool crcPass, pyldComplete; bool crcPass, pyldComplete;
crcPass = build(iv->id, &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 (!crcPass && !pyldComplete) { // payload not complete
if ((mPayload[iv->id].requested) && (retransmit)) { if ((mPayload[iv->id].requested) && (retransmit)) {
if (iv->devControlCmd == Restart || iv->devControlCmd == CleanState_LockAndAlarm) { if (iv->devControlCmd == Restart || iv->devControlCmd == CleanState_LockAndAlarm) {
@ -433,7 +454,8 @@ const byteAssign_t InfoAssignment[] = {
} else if(iv->devControlCmd == ActivePowerContr) { } else if(iv->devControlCmd == ActivePowerContr) {
DPRINT_IVID(DBG_INFO, iv->id); DPRINT_IVID(DBG_INFO, iv->id);
DBGPRINTLN(F("retransmit power limit")); 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 { } else {
uint8_t cmd = mPayload[iv->id].txCmd; uint8_t cmd = mPayload[iv->id].txCmd;
if (mPayload[iv->id].retransmits < mMaxRetrans) { if (mPayload[iv->id].retransmits < mMaxRetrans) {
@ -444,7 +466,8 @@ const byteAssign_t InfoAssignment[] = {
mPayload[iv->id].retransmits = mMaxRetrans; mPayload[iv->id].retransmits = mMaxRetrans;
} else if ( cmd == 0x0f ) { } else if ( cmd == 0x0f ) {
//hard/firmware request //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(); //iv->setQueuedCmdFinished();
//cmd = iv->getQueuedCmd(); //cmd = iv->getQueuedCmd();
} else { } else {
@ -481,7 +504,8 @@ const byteAssign_t InfoAssignment[] = {
} }
DBGPRINT(F(" 0x")); DBGPRINT(F(" 0x"));
DBGHEXLN(cmd); 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); //mSys->Radio.prepareDevInformCmd(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex, true, cmd);
yield(); yield();
} }
@ -499,7 +523,8 @@ const byteAssign_t InfoAssignment[] = {
DBGPRINT(F("prepareDevInformCmd 0x")); DBGPRINT(F("prepareDevInformCmd 0x"));
DBGHEXLN(mPayload[iv->id].txCmd); 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, 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 /*else { // payload complete
@ -568,6 +593,7 @@ const byteAssign_t InfoAssignment[] = {
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); // choose the record structure record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); // choose the record structure
rec->ts = mPayload[iv->id].ts; rec->ts = mPayload[iv->id].ts;
mPayload[iv->id].gotFragment = true; mPayload[iv->id].gotFragment = true;
mPayload[iv->id].fragments++;
mPayload[iv->id].txId = p->packet[0]; mPayload[iv->id].txId = p->packet[0];
miStsConsolidate(iv, stschan, rec, p->packet[10], p->packet[12], p->packet[9], p->packet[11]); miStsConsolidate(iv, stschan, rec, p->packet[10], p->packet[12], p->packet[9], p->packet[11]);
mPayload[iv->id].stsAB[stschan] = true; mPayload[iv->id].stsAB[stschan] = true;
@ -639,6 +665,7 @@ const byteAssign_t InfoAssignment[] = {
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); // choose the parser record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); // choose the parser
rec->ts = mPayload[iv->id].ts; rec->ts = mPayload[iv->id].ts;
mPayload[iv->id].gotFragment = true; mPayload[iv->id].gotFragment = true;
mPayload[iv->id].fragments++;
uint8_t datachan = ( p->packet[0] == 0x89 || p->packet[0] == (0x36 + ALL_FRAMES) ) ? CH1 : 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 : ( 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) ) { if (p->packet[0] < (0x39 + ALL_FRAMES) ) {
/*uint8_t cmd = p->packet[0] - ALL_FRAMES + 1; /*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 = cmd;*/
mPayload[iv->id].txCmd++; mPayload[iv->id].txCmd++;
mPayload[iv->id].retransmits = 0; // reserve retransmissions for each response mPayload[iv->id].retransmits = 0; // reserve retransmissions for each response
@ -765,7 +793,7 @@ const byteAssign_t InfoAssignment[] = {
uint8_t txCmd = mPayload[id].txCmd; uint8_t txCmd = mPayload[id].txCmd;
if(!*complete) { 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); //DBGHEXLN(txCmd);
if (txCmd == 0x09 || txCmd == 0x11 || (txCmd >= 0x36 && txCmd <= 0x39)) if (txCmd == 0x09 || txCmd == 0x11 || (txCmd >= 0x36 && txCmd <= 0x39))
return false; return false;
@ -800,6 +828,8 @@ const byteAssign_t InfoAssignment[] = {
DBGPRINTLN(F("resetPayload")); DBGPRINTLN(F("resetPayload"));
memset(mPayload[id].len, 0, MAX_PAYLOAD_ENTRIES); memset(mPayload[id].len, 0, MAX_PAYLOAD_ENTRIES);
mPayload[id].gotFragment = false; mPayload[id].gotFragment = false;
mPayload[id].fragments = 0;
mPayload[id].lastFragments = 0;
/*mPayload[id].maxPackId = MAX_PAYLOAD_ENTRIES; /*mPayload[id].maxPackId = MAX_PAYLOAD_ENTRIES;
mPayload[id].lastFound = false;*/ mPayload[id].lastFound = false;*/
mPayload[id].retransmits = 0; mPayload[id].retransmits = 0;

Loading…
Cancel
Save