mirror of
https://github.com/lumapu/ahoy.git
synced 2025-07-17 16:27:12 +02:00
0.8.16
* updated heuristic #1080 #1259 * fix compile opendtufusion fusion ethernet
This commit is contained in:
parent
4afd63184d
commit
240be8cd98
5 changed files with 83 additions and 66 deletions
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
## 0.8.16 - 2023-12-09
|
## 0.8.16 - 2023-12-09
|
||||||
* fix crash if NRF is not enabled
|
* fix crash if NRF is not enabled
|
||||||
|
* updated heuristic #1080 #1259
|
||||||
|
* fix compile opendtufusion fusion ethernet
|
||||||
|
|
||||||
## 0.8.15 - 2023-12-09
|
## 0.8.15 - 2023-12-09
|
||||||
* added support for opendtufusion fusion ethernet shield #886
|
* added support for opendtufusion fusion ethernet shield #886
|
||||||
|
|
|
@ -88,7 +88,6 @@ class Communication : public CommQueue<> {
|
||||||
} else
|
} else
|
||||||
q->iv->radio->prepareDevInformCmd(q->iv, q->cmd, q->ts, q->iv->alarmLastId, false);
|
q->iv->radio->prepareDevInformCmd(q->iv, q->cmd, q->ts, q->iv->alarmLastId, false);
|
||||||
|
|
||||||
if(!mHeu.getTestModeEnabled(q->iv))
|
|
||||||
q->iv->radioStatistics.txCnt++;
|
q->iv->radioStatistics.txCnt++;
|
||||||
mWaitTimeout = millis() + timeout;
|
mWaitTimeout = millis() + timeout;
|
||||||
mWaitTimeout_min = millis() + timeout_min;
|
mWaitTimeout_min = millis() + timeout_min;
|
||||||
|
@ -115,7 +114,6 @@ class Communication : public CommQueue<> {
|
||||||
}
|
}
|
||||||
mFirstTry = false;
|
mFirstTry = false;
|
||||||
mlastTO_min = timeout_min;
|
mlastTO_min = timeout_min;
|
||||||
if(!mHeu.getTestModeEnabled(q->iv))
|
|
||||||
q->iv->radioStatistics.retransmits++; // got nothing
|
q->iv->radioStatistics.retransmits++; // got nothing
|
||||||
mState = States::START;
|
mState = States::START;
|
||||||
break;
|
break;
|
||||||
|
@ -166,6 +164,7 @@ class Communication : public CommQueue<> {
|
||||||
DBGPRINT(String(p->ch));
|
DBGPRINT(String(p->ch));
|
||||||
DBGPRINT(F(" "));
|
DBGPRINT(F(" "));
|
||||||
} else {
|
} else {
|
||||||
|
DBGPRINT(F(" "));
|
||||||
DBGPRINT(String(p->rssi));
|
DBGPRINT(String(p->rssi));
|
||||||
DBGPRINT(F("dBm | "));
|
DBGPRINT(F("dBm | "));
|
||||||
}
|
}
|
||||||
|
@ -180,7 +179,6 @@ class Communication : public CommQueue<> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(checkIvSerial(&p->packet[1], q->iv)) {
|
if(checkIvSerial(&p->packet[1], q->iv)) {
|
||||||
if(!mHeu.getTestModeEnabled(q->iv))
|
|
||||||
q->iv->radioStatistics.frmCnt++;
|
q->iv->radioStatistics.frmCnt++;
|
||||||
|
|
||||||
if (p->packet[0] == (TX_REQ_INFO + ALL_FRAMES)) { // response from get information command
|
if (p->packet[0] == (TX_REQ_INFO + ALL_FRAMES)) { // response from get information command
|
||||||
|
@ -193,7 +191,6 @@ class Communication : public CommQueue<> {
|
||||||
parseMiFrame(p, q);
|
parseMiFrame(p, q);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(!mHeu.getTestModeEnabled(q->iv))
|
|
||||||
q->iv->radioStatistics.rxFail++; // got no complete payload
|
q->iv->radioStatistics.rxFail++; // got no complete payload
|
||||||
DPRINTLN(DBG_WARN, F("Inverter serial does not match"));
|
DPRINTLN(DBG_WARN, F("Inverter serial does not match"));
|
||||||
mWaitTimeout = millis() + timeout;
|
mWaitTimeout = millis() + timeout;
|
||||||
|
@ -370,8 +367,7 @@ class Communication : public CommQueue<> {
|
||||||
DBGPRINT(F("CRC Error "));
|
DBGPRINT(F("CRC Error "));
|
||||||
if(q->attempts == 0) {
|
if(q->attempts == 0) {
|
||||||
DBGPRINTLN(F("-> Fail"));
|
DBGPRINTLN(F("-> Fail"));
|
||||||
/*if(!mHeu.getTestModeEnabled())
|
/*q->iv->radioStatistics.rxFail++; // got fragments but not complete response
|
||||||
q->iv->radioStatistics.rxFail++; // got fragments but not complete response
|
|
||||||
cmdDone();*/
|
cmdDone();*/
|
||||||
closeRequest(q->iv, false, false);
|
closeRequest(q->iv, false, false);
|
||||||
|
|
||||||
|
@ -420,8 +416,7 @@ class Communication : public CommQueue<> {
|
||||||
DBGPRINT(String(rec->pyldLen));
|
DBGPRINT(String(rec->pyldLen));
|
||||||
DBGPRINTLN(F(" bytes"));
|
DBGPRINTLN(F(" bytes"));
|
||||||
}
|
}
|
||||||
/*if(!mHeu.getTestModeEnabled())
|
/*q->iv->radioStatistics.rxFail++;*/
|
||||||
q->iv->radioStatistics.rxFail++;*/
|
|
||||||
closeRequest(q->iv, false, false);
|
closeRequest(q->iv, false, false);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -464,14 +459,11 @@ class Communication : public CommQueue<> {
|
||||||
// ordering of lines is relevant for statistics
|
// ordering of lines is relevant for statistics
|
||||||
if(succeeded) {
|
if(succeeded) {
|
||||||
mHeu.setGotAll(iv);
|
mHeu.setGotAll(iv);
|
||||||
if(!mHeu.getTestModeEnabled(iv))
|
|
||||||
iv->radioStatistics.rxSuccess++;
|
iv->radioStatistics.rxSuccess++;
|
||||||
} else if(iv->mGotFragment) {
|
} else if(iv->mGotFragment) {
|
||||||
mHeu.setGotFragment(iv);
|
mHeu.setGotFragment(iv);
|
||||||
if(!mHeu.getTestModeEnabled(iv))
|
|
||||||
iv->radioStatistics.rxFail++; // got no complete payload
|
iv->radioStatistics.rxFail++; // got no complete payload
|
||||||
} else {
|
} else {
|
||||||
if(!mHeu.getTestModeEnabled(iv))
|
|
||||||
iv->radioStatistics.rxFailNoAnser++; // got nothing
|
iv->radioStatistics.rxFailNoAnser++; // got nothing
|
||||||
mHeu.setGotNothing(iv);
|
mHeu.setGotNothing(iv);
|
||||||
mWaitTimeout = millis() + WAIT_GAP_TIMEOUT;
|
mWaitTimeout = millis() + WAIT_GAP_TIMEOUT;
|
||||||
|
@ -682,12 +674,10 @@ class Communication : public CommQueue<> {
|
||||||
|
|
||||||
if(q->iv->miMultiParts == 7) {
|
if(q->iv->miMultiParts == 7) {
|
||||||
mHeu.setGotAll(q->iv);
|
mHeu.setGotAll(q->iv);
|
||||||
if(!mHeu.getTestModeEnabled(q->iv))
|
|
||||||
q->iv->radioStatistics.rxSuccess++;
|
q->iv->radioStatistics.rxSuccess++;
|
||||||
} else
|
} else
|
||||||
mHeu.setGotFragment(q->iv);
|
mHeu.setGotFragment(q->iv);
|
||||||
/*if(!mHeu.getTestModeEnabled())
|
/*iv->radioStatistics.rxFail++; // got no complete payload*/
|
||||||
iv->radioStatistics.rxFail++; // got no complete payload*/
|
|
||||||
//q->iv->radioStatistics.retransmits++;
|
//q->iv->radioStatistics.retransmits++;
|
||||||
q->iv->radio->sendCmdPacket(q->iv, cmd, 0x00, true);
|
q->iv->radio->sendCmdPacket(q->iv, cmd, 0x00, true);
|
||||||
|
|
||||||
|
|
|
@ -10,61 +10,79 @@
|
||||||
#include "hmInverter.h"
|
#include "hmInverter.h"
|
||||||
#include "HeuristicInv.h"
|
#include "HeuristicInv.h"
|
||||||
|
|
||||||
|
#define RF_TEST_PERIOD_MAX_SEND_CNT 50
|
||||||
|
#define RF_TEST_PERIOD_MAX_FAIL_CNT 5
|
||||||
|
|
||||||
|
#define RF_TX_TEST_CHAN_1ST_USE 0xff
|
||||||
|
|
||||||
class Heuristic {
|
class Heuristic {
|
||||||
public:
|
public:
|
||||||
uint8_t getTxCh(Inverter<> *iv) {
|
uint8_t getTxCh(Inverter<> *iv) {
|
||||||
if((IV_HMS == iv->ivGen) || (IV_HMT == iv->ivGen))
|
if((IV_HMS == iv->ivGen) || (IV_HMT == iv->ivGen))
|
||||||
return 0; // not used for these inverter types
|
return 0; // not used for these inverter types
|
||||||
|
|
||||||
uint8_t bestId = 0;
|
HeuristicInv *ih = &iv->heuristics;
|
||||||
int8_t bestQuality = -6;
|
|
||||||
for(uint8_t i = 0; i < RF_MAX_CHANNEL_ID; i++) {
|
// start with the next index: round robbin in case of same 'best' quality
|
||||||
if(iv->heuristics.txRfQuality[i] > bestQuality) {
|
uint8_t curId = (ih->txRfChId + 1) % RF_MAX_CHANNEL_ID;
|
||||||
bestQuality = iv->heuristics.txRfQuality[i];
|
uint8_t lastBestId = ih->txRfChId;
|
||||||
bestId = i;
|
ih->txRfChId = curId;
|
||||||
}
|
curId = (curId + 1) % RF_MAX_CHANNEL_ID;
|
||||||
|
for(uint8_t i = 1; i < RF_MAX_CHANNEL_ID; i++) {
|
||||||
|
if(ih->txRfQuality[curId] > ih->txRfQuality[ih->txRfChId])
|
||||||
|
ih->txRfChId = curId;
|
||||||
|
curId = (curId + 1) % RF_MAX_CHANNEL_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(iv->heuristics.testEn) {
|
if(ih->testPeriodSendCnt < 0xff)
|
||||||
DPRINTLN(DBG_INFO, F("heuristic test mode"));
|
ih->testPeriodSendCnt++;
|
||||||
iv->heuristics.testIdx = (iv->heuristics.testIdx + 1) % RF_MAX_CHANNEL_ID;
|
|
||||||
|
|
||||||
if (iv->heuristics.testIdx == bestId)
|
if((ih->txRfChId == lastBestId) && (ih->testPeriodSendCnt >= RF_TEST_PERIOD_MAX_SEND_CNT)) {
|
||||||
iv->heuristics.testIdx = (iv->heuristics.testIdx + 1) % RF_MAX_CHANNEL_ID;
|
if(ih->testPeriodFailCnt > RF_TEST_PERIOD_MAX_FAIL_CNT) {
|
||||||
|
// try round robbin another chan and see if it works even better
|
||||||
|
ih->testChId = (ih->testChId + 1) % RF_MAX_CHANNEL_ID;
|
||||||
|
if(ih->testChId = ih->txRfChId)
|
||||||
|
ih->testChId = (ih->testChId + 1) % RF_MAX_CHANNEL_ID;
|
||||||
|
|
||||||
// test channel get's quality of best channel (maybe temporarily, see in 'setGotNothing')
|
// give it a fair chance but remember old status in case of immediate fail
|
||||||
iv->heuristics.storedIdx = iv->heuristics.txRfQuality[iv->heuristics.testIdx];
|
ih->txRfChId = ih->testChId;
|
||||||
iv->heuristics.txRfQuality[iv->heuristics.testIdx] = bestQuality;
|
ih->testChId = RF_TX_TEST_CHAN_1ST_USE; // mark the chan as a test and as 1st use during new test period
|
||||||
|
DPRINTLN(DBG_INFO, "Test CH " + String(id2Ch(ih->txRfChId)));
|
||||||
|
}
|
||||||
|
|
||||||
iv->heuristics.txRfChId = iv->heuristics.testIdx;
|
// start new test period
|
||||||
} else
|
ih->testPeriodSendCnt = 0;
|
||||||
iv->heuristics.txRfChId = bestId;
|
ih->testPeriodFailCnt = 0;
|
||||||
|
} else if(ih->txRfChId != lastBestId) {
|
||||||
|
// start new test period
|
||||||
|
ih->testPeriodSendCnt = 0;
|
||||||
|
ih->testPeriodFailCnt = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return id2Ch(iv->heuristics.txRfChId);
|
return id2Ch(ih->txRfChId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setGotAll(Inverter<> *iv) {
|
void setGotAll(Inverter<> *iv) {
|
||||||
updateQuality(iv, 2); // GOOD
|
updateQuality(iv, 2); // GOOD
|
||||||
iv->heuristics.testEn = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setGotFragment(Inverter<> *iv) {
|
void setGotFragment(Inverter<> *iv) {
|
||||||
updateQuality(iv, 1); // OK
|
updateQuality(iv, 1); // OK
|
||||||
iv->heuristics.testEn = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setGotNothing(Inverter<> *iv) {
|
void setGotNothing(Inverter<> *iv) {
|
||||||
if(RF_NA != iv->heuristics.storedIdx) {
|
HeuristicInv *ih = &iv->heuristics;
|
||||||
// if communication fails on first try with temporarily good level, revert it back to its original level
|
|
||||||
iv->heuristics.txRfQuality[iv->heuristics.txRfChId] = iv->heuristics.storedIdx;
|
if(RF_TX_TEST_CHAN_1ST_USE == ih->testChId) {
|
||||||
iv->heuristics.storedIdx = RF_NA;
|
// immediate fail
|
||||||
|
ih->testChId = ih->txRfChId; // reset to best
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!iv->heuristics.testEn) {
|
if(ih->testPeriodFailCnt < 0xff)
|
||||||
|
ih->testPeriodFailCnt++;
|
||||||
|
|
||||||
updateQuality(iv, -2); // BAD
|
updateQuality(iv, -2); // BAD
|
||||||
iv->heuristics.testEn = true;
|
|
||||||
} else
|
|
||||||
iv->heuristics.testEn = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void printStatus(Inverter<> *iv) {
|
void printStatus(Inverter<> *iv) {
|
||||||
|
@ -86,17 +104,15 @@ class Heuristic {
|
||||||
DBGPRINTLN(String(iv->config->powerLevel));
|
DBGPRINTLN(String(iv->config->powerLevel));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool getTestModeEnabled(Inverter<> *iv) {
|
|
||||||
return iv->heuristics.testEn;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void updateQuality(Inverter<> *iv, uint8_t quality) {
|
void updateQuality(Inverter<> *iv, uint8_t quality) {
|
||||||
iv->heuristics.txRfQuality[iv->heuristics.txRfChId] += quality;
|
HeuristicInv *ih = &iv->heuristics;
|
||||||
if(iv->heuristics.txRfQuality[iv->heuristics.txRfChId] > RF_MAX_QUALITY)
|
|
||||||
iv->heuristics.txRfQuality[iv->heuristics.txRfChId] = RF_MAX_QUALITY;
|
ih->txRfQuality[ih->txRfChId] += quality;
|
||||||
else if(iv->heuristics.txRfQuality[iv->heuristics.txRfChId] < RF_MIN_QUALTIY)
|
if(ih->txRfQuality[ih->txRfChId] > RF_MAX_QUALITY)
|
||||||
iv->heuristics.txRfQuality[iv->heuristics.txRfChId] = RF_MIN_QUALTIY;
|
ih->txRfQuality[ih->txRfChId] = RF_MAX_QUALITY;
|
||||||
|
else if(ih->txRfQuality[ih->txRfChId] < RF_MIN_QUALTIY)
|
||||||
|
ih->txRfQuality[ih->txRfChId] = RF_MIN_QUALTIY;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint8_t id2Ch(uint8_t id) {
|
inline uint8_t id2Ch(uint8_t id) {
|
||||||
|
|
|
@ -13,12 +13,17 @@
|
||||||
|
|
||||||
class HeuristicInv {
|
class HeuristicInv {
|
||||||
public:
|
public:
|
||||||
int8_t txRfQuality[5]; // heuristics tx quality (check 'Heuristics.h')
|
HeuristicInv() {
|
||||||
uint8_t txRfChId; // RF TX channel id
|
memset(txRfQuality, -6, RF_MAX_CHANNEL_ID);
|
||||||
|
}
|
||||||
|
|
||||||
bool testEn = false;
|
public:
|
||||||
uint8_t testIdx = 0;
|
int8_t txRfQuality[RF_MAX_CHANNEL_ID]; // heuristics tx quality (check 'Heuristics.h')
|
||||||
int8_t storedIdx = RF_NA;
|
uint8_t txRfChId = 0; // RF TX channel id
|
||||||
|
|
||||||
|
uint8_t testPeriodSendCnt = 0;
|
||||||
|
uint8_t testPeriodFailCnt = 0;
|
||||||
|
uint8_t testChId = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /*__HEURISTIC_INV_H__*/
|
#endif /*__HEURISTIC_INV_H__*/
|
||||||
|
|
|
@ -35,7 +35,11 @@ class HmRadio : public Radio {
|
||||||
HmRadio() {
|
HmRadio() {
|
||||||
mDtuSn = DTU_SN;
|
mDtuSn = DTU_SN;
|
||||||
mIrqRcvd = false;
|
mIrqRcvd = false;
|
||||||
|
#if defined(CONFIG_IDF_TARGET_ESP32S3) && defined(ETHERNET)
|
||||||
|
mNrf24.reset(new RF24());
|
||||||
|
#else
|
||||||
mNrf24.reset(new RF24(CE_PIN, CS_PIN, SPI_SPEED));
|
mNrf24.reset(new RF24(CE_PIN, CS_PIN, SPI_SPEED));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
~HmRadio() {}
|
~HmRadio() {}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue