mirror of
https://github.com/lumapu/ahoy.git
synced 2025-06-11 15:11:38 +02:00
* optimized heuristic
* added option to reduce log size (strip frame payload to relevant field) thx @Oberfritze, @rejoe2
This commit is contained in:
parent
bac4301b8a
commit
f417717fc3
10 changed files with 114 additions and 69 deletions
|
@ -32,11 +32,11 @@ void app::setup() {
|
|||
DBGPRINTLN(F("false"));
|
||||
|
||||
if(mConfig->nrf.enabled) {
|
||||
mNrfRadio.setup(&mConfig->serial.debug, &mConfig->serial.privacyLog, mConfig->nrf.pinIrq, mConfig->nrf.pinCe, mConfig->nrf.pinCs, mConfig->nrf.pinSclk, mConfig->nrf.pinMosi, mConfig->nrf.pinMiso);
|
||||
mNrfRadio.setup(&mConfig->serial.debug, &mConfig->serial.privacyLog, &mConfig->serial.printWholeTrace, mConfig->nrf.pinIrq, mConfig->nrf.pinCe, mConfig->nrf.pinCs, mConfig->nrf.pinSclk, mConfig->nrf.pinMosi, mConfig->nrf.pinMiso);
|
||||
}
|
||||
#if defined(ESP32)
|
||||
if(mConfig->cmt.enabled) {
|
||||
mCmtRadio.setup(&mConfig->serial.debug, &mConfig->serial.privacyLog, mConfig->cmt.pinSclk, mConfig->cmt.pinSdio, mConfig->cmt.pinCsb, mConfig->cmt.pinFcsb, false);
|
||||
mCmtRadio.setup(&mConfig->serial.debug, &mConfig->serial.privacyLog, &mConfig->serial.printWholeTrace, mConfig->cmt.pinSclk, mConfig->cmt.pinSdio, mConfig->cmt.pinCsb, mConfig->cmt.pinFcsb, false);
|
||||
}
|
||||
#endif
|
||||
#ifdef ETHERNET
|
||||
|
@ -55,7 +55,7 @@ void app::setup() {
|
|||
#endif
|
||||
#endif /* defined(ETHERNET) */
|
||||
|
||||
mCommunication.setup(&mTimestamp, &mConfig->serial.debug, &mConfig->serial.privacyLog);
|
||||
mCommunication.setup(&mTimestamp, &mConfig->serial.debug, &mConfig->serial.privacyLog, &mConfig->serial.printWholeTrace);
|
||||
mCommunication.addPayloadListener(std::bind(&app::payloadEventListener, this, std::placeholders::_1, std::placeholders::_2));
|
||||
mSys.setup(&mTimestamp, &mConfig->inst);
|
||||
for (uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) {
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
* https://arduino-esp8266.readthedocs.io/en/latest/filesystem.html#flash-layout
|
||||
* */
|
||||
|
||||
#define CONFIG_VERSION 2
|
||||
#define CONFIG_VERSION 3
|
||||
|
||||
|
||||
#define PROT_MASK_INDEX 0x0001
|
||||
|
@ -117,6 +117,7 @@ typedef struct {
|
|||
bool showIv;
|
||||
bool debug;
|
||||
bool privacyLog;
|
||||
bool printWholeTrace;
|
||||
} cfgSerial_t;
|
||||
|
||||
typedef struct {
|
||||
|
@ -426,6 +427,7 @@ class settings {
|
|||
mCfg.serial.showIv = false;
|
||||
mCfg.serial.debug = false;
|
||||
mCfg.serial.privacyLog = true;
|
||||
mCfg.serial.printWholeTrace = true;
|
||||
|
||||
mCfg.mqtt.port = DEF_MQTT_PORT;
|
||||
snprintf(mCfg.mqtt.broker, MQTT_ADDR_LEN, "%s", DEF_MQTT_BROKER);
|
||||
|
@ -476,6 +478,9 @@ class settings {
|
|||
mCfg.inst.iv[i].disNightCom = false;
|
||||
mCfg.inst.iv[i].add2Total = true;
|
||||
}
|
||||
if(mCfg.configVersion < 3) {
|
||||
mCfg.serial.printWholeTrace = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -620,10 +625,12 @@ class settings {
|
|||
obj[F("show")] = mCfg.serial.showIv;
|
||||
obj[F("debug")] = mCfg.serial.debug;
|
||||
obj[F("prv")] = (bool) mCfg.serial.privacyLog;
|
||||
obj[F("trc")] = (bool) mCfg.serial.printWholeTrace;
|
||||
} else {
|
||||
getVal<bool>(obj, F("show"), &mCfg.serial.showIv);
|
||||
getVal<bool>(obj, F("debug"), &mCfg.serial.debug);
|
||||
getVal<bool>(obj, F("prv"), &mCfg.serial.privacyLog);
|
||||
getVal<bool>(obj, F("trc"), &mCfg.serial.printWholeTrace);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#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 65 // timeout for single frame requests
|
||||
#define WAIT_GAP_TIMEOUT 200 // timeout after no complete payload
|
||||
#define MAX_BUFFER 250
|
||||
|
||||
typedef std::function<void(uint8_t, Inverter<> *)> payloadListenerType;
|
||||
|
@ -22,10 +23,11 @@ typedef std::function<void(Inverter<> *)> alarmListenerType;
|
|||
|
||||
class Communication : public CommQueue<> {
|
||||
public:
|
||||
void setup(uint32_t *timestamp, bool *serialDebug, bool *privacyMode) {
|
||||
void setup(uint32_t *timestamp, bool *serialDebug, bool *privacyMode, bool *printWholeTrace) {
|
||||
mTimestamp = timestamp;
|
||||
mPrivacyMode = privacyMode;
|
||||
mSerialDebug = serialDebug;
|
||||
mPrintWholeTrace = printWholeTrace;
|
||||
}
|
||||
|
||||
void addImportant(Inverter<> *iv, uint8_t cmd, bool delOnPop = true) {
|
||||
|
@ -47,7 +49,7 @@ class Communication : public CommQueue<> {
|
|||
return; // empty
|
||||
|
||||
uint16_t timeout = (q->iv->ivGen == IV_MI) ? MI_TIMEOUT : ((q->iv->mGotFragment && q->iv->mGotLastMsg) || mIsResend) ? SINGLEFR_TIMEOUT : DEFAULT_TIMEOUT;
|
||||
uint16_t timeout_min = (q->iv->ivGen == IV_MI) ? MI_TIMEOUT : ((q->iv->mGotFragment) ? SINGLEFR_TIMEOUT : FRSTMSG_TIMEOUT);
|
||||
uint16_t timeout_min = (q->iv->ivGen == IV_MI) ? MI_TIMEOUT : ((q->iv->mGotFragment || mIsResend)) ? SINGLEFR_TIMEOUT : FRSTMSG_TIMEOUT;
|
||||
|
||||
switch(mState) {
|
||||
case States::RESET:
|
||||
|
@ -63,6 +65,7 @@ class Communication : public CommQueue<> {
|
|||
mHeu.getTxCh(q->iv);
|
||||
q->iv->mGotFragment = false;
|
||||
q->iv->mGotLastMsg = false;
|
||||
mIsResend = false;
|
||||
if(NULL == q->iv->radio)
|
||||
cmdDone(true); // can't communicate while radio is not defined!
|
||||
mState = States::START;
|
||||
|
@ -97,7 +100,9 @@ class Communication : public CommQueue<> {
|
|||
|
||||
case States::WAIT:
|
||||
if(millis() > mWaitTimeout_min) {
|
||||
if(q->iv->mGotFragment) { // nothing received yet?
|
||||
if(mIsResend) { // we already have been through...
|
||||
mWaitTimeout = mWaitTimeout_min;
|
||||
} else if(q->iv->mGotFragment) { // nothing received yet?
|
||||
if(q->iv->mGotLastMsg) {
|
||||
//mState = States::CHECK_FRAMES;
|
||||
mWaitTimeout = mWaitTimeout_min;
|
||||
|
@ -123,8 +128,7 @@ class Communication : public CommQueue<> {
|
|||
break;
|
||||
|
||||
case States::CHECK_FRAMES: {
|
||||
if((!q->iv->radio->get() && !mIsResend) || ((q->iv->mGotFragment) && (0 == q->attempts))) { // radio buffer empty
|
||||
//cmdDone();
|
||||
if((!q->iv->radio->get() && !mIsResend) || (((q->iv->mGotFragment) || (mIsResend)) && (0 == q->attempts))) { // radio buffer empty or no more answers
|
||||
if(*mSerialDebug) {
|
||||
DPRINT_IVID(DBG_INFO, q->iv->id);
|
||||
DBGPRINT(F("request timeout: "));
|
||||
|
@ -153,21 +157,26 @@ class Communication : public CommQueue<> {
|
|||
if(p->millis < 100)
|
||||
DBGPRINT(F(" "));
|
||||
DBGPRINT(String(p->millis));
|
||||
DBGPRINT(F("ms "));
|
||||
DBGPRINT(F("ms | "));
|
||||
DBGPRINT(String(p->len));
|
||||
if((IV_HM == q->iv->ivGen) || (IV_MI == q->iv->ivGen)) {
|
||||
DBGPRINT(F(" CH"));
|
||||
if(3 == p->ch)
|
||||
DBGPRINT(F("0"));
|
||||
DBGPRINT(String(p->ch));
|
||||
}
|
||||
DBGPRINT(F(", "));
|
||||
} else {
|
||||
DBGPRINT(String(p->rssi));
|
||||
DBGPRINT(F("dBm | "));
|
||||
}
|
||||
if(*mPrintWholeTrace) {
|
||||
if(*mPrivacyMode)
|
||||
ah::dumpBuf(p->packet, p->len, 1, 8);
|
||||
else
|
||||
ah::dumpBuf(p->packet, p->len);
|
||||
} else {
|
||||
DBGPRINT(F("frm "));
|
||||
DBGHEXLN(p->packet[9]);
|
||||
}
|
||||
|
||||
if(checkIvSerial(&p->packet[1], q->iv)) {
|
||||
if(!mHeu.getTestModeEnabled())
|
||||
|
@ -178,7 +187,7 @@ class Communication : public CommQueue<> {
|
|||
nextState = States::CHECK_PACKAGE;
|
||||
} else if (p->packet[0] == (TX_REQ_DEVCONTROL + ALL_FRAMES)) { // response from dev control command
|
||||
parseDevCtrl(p, q);
|
||||
cmdDone(true); // remove done request
|
||||
closeRequest(q->iv, true);
|
||||
} else if(IV_MI == q->iv->ivGen) {
|
||||
parseMiFrame(p, q);
|
||||
}
|
||||
|
@ -198,17 +207,18 @@ class Communication : public CommQueue<> {
|
|||
if(q->iv->ivGen != IV_MI)
|
||||
mState = nextState;
|
||||
else {
|
||||
if( q->iv->miMultiParts > 5 &&
|
||||
((q->cmd == 0x39) && (q->iv->type == INV_TYPE_4CH) ||
|
||||
if(q->iv->miMultiParts < 6) {
|
||||
nextState = States::WAIT;
|
||||
} else {
|
||||
if((q->cmd == 0x39) && (q->iv->type == INV_TYPE_4CH) ||
|
||||
(q->cmd == MI_REQ_CH2) && (q->iv->type == INV_TYPE_2CH) ||
|
||||
(q->cmd == MI_REQ_CH1) && (q->iv->type == INV_TYPE_1CH))) {
|
||||
(q->cmd == MI_REQ_CH1) && (q->iv->type == INV_TYPE_1CH)) {
|
||||
miComplete(q->iv);
|
||||
//closeRequest(q->iv, q->iv->miMultiParts > 5);
|
||||
} else if (q->iv->miMultiParts > 5)
|
||||
closeRequest(q->iv, true);
|
||||
else {
|
||||
nextState = States::WAIT;
|
||||
}
|
||||
closeRequest(q->iv, true);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -240,12 +250,14 @@ class Communication : public CommQueue<> {
|
|||
if(framnr) {
|
||||
setAttempt();
|
||||
|
||||
if(*mSerialDebug) {
|
||||
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);
|
||||
mIsResend = true;
|
||||
mlastTO_min = timeout_min;
|
||||
|
@ -461,11 +473,13 @@ class Communication : public CommQueue<> {
|
|||
if(!mHeu.getTestModeEnabled())
|
||||
iv->radioStatistics.rxFailNoAnser++; // got nothing
|
||||
mHeu.setGotNothing(iv);
|
||||
mWaitTimeout = millis() + WAIT_GAP_TIMEOUT;
|
||||
}
|
||||
cmdDone(delCmd);
|
||||
iv->mGotFragment = false;
|
||||
iv->mGotLastMsg = false;
|
||||
iv->miMultiParts = 0;
|
||||
mIsResend = false;
|
||||
mFirstTry = false; // for correct reset
|
||||
mState = States::RESET;
|
||||
}
|
||||
|
@ -788,7 +802,7 @@ class Communication : public CommQueue<> {
|
|||
// update status state-machine,
|
||||
if (ac_pow)
|
||||
iv->isProducing();
|
||||
closeRequest(iv, iv->miMultiParts > 5);
|
||||
//closeRequest(iv, iv->miMultiParts > 5);
|
||||
|
||||
//mHeu.setGotAll(iv);
|
||||
//cmdDone(true);
|
||||
|
@ -812,7 +826,7 @@ class Communication : public CommQueue<> {
|
|||
private:
|
||||
States mState = States::RESET;
|
||||
uint32_t *mTimestamp;
|
||||
bool *mPrivacyMode, *mSerialDebug;
|
||||
bool *mPrivacyMode, *mSerialDebug, *mPrintWholeTrace;
|
||||
uint32_t mWaitTimeout = 0;
|
||||
uint32_t mWaitTimeout_min = 0;
|
||||
std::array<frame_t, MAX_PAYLOAD_ENTRIES> mLocalBuf;
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#define RF_MAX_CHANNEL_ID 5
|
||||
#define RF_MAX_QUALITY 4
|
||||
#define RF_MIN_QUALTIY -6
|
||||
#define RF_NA -99
|
||||
|
||||
class Heuristic {
|
||||
public:
|
||||
|
@ -19,25 +20,29 @@ class Heuristic {
|
|||
if((IV_HMS == iv->ivGen) || (IV_HMT == iv->ivGen))
|
||||
return 0; // not used for these inverter types
|
||||
|
||||
mCycle++; // intended to overflow from time to time
|
||||
if(mTestEn) {
|
||||
iv->txRfChId = mCycle % RF_MAX_CHANNEL_ID;
|
||||
DPRINTLN(DBG_INFO, F("heuristic test mode"));
|
||||
return id2Ch(iv->txRfChId);
|
||||
}
|
||||
|
||||
uint8_t id = 0;
|
||||
uint8_t bestId = 0;
|
||||
int8_t bestQuality = -6;
|
||||
for(uint8_t i = 0; i < RF_MAX_CHANNEL_ID; i++) {
|
||||
if(iv->txRfQuality[i] > bestQuality) {
|
||||
bestQuality = iv->txRfQuality[i];
|
||||
id = i;
|
||||
bestId = i;
|
||||
}
|
||||
}
|
||||
if(bestQuality == -6)
|
||||
iv->txRfChId = (iv->txRfChId + 1) % RF_MAX_CHANNEL_ID; // next channel
|
||||
else
|
||||
iv->txRfChId = id; // best quality channel
|
||||
|
||||
if(mTestEn) {
|
||||
DPRINTLN(DBG_INFO, F("heuristic test mode"));
|
||||
mTestIdx = (mTestIdx + 1) % RF_MAX_CHANNEL_ID;
|
||||
|
||||
if (mTestIdx == bestId)
|
||||
mTestIdx = (mTestIdx + 1) % RF_MAX_CHANNEL_ID;
|
||||
|
||||
// test channel get's quality of best channel (maybe temporarily, see in 'setGotNothing')
|
||||
mStoredIdx = iv->txRfQuality[mTestIdx];
|
||||
iv->txRfQuality[mTestIdx] = bestQuality;
|
||||
|
||||
iv->txRfChId = mTestIdx;
|
||||
} else
|
||||
iv->txRfChId = bestId;
|
||||
|
||||
return id2Ch(iv->txRfChId);
|
||||
}
|
||||
|
@ -53,10 +58,15 @@ class Heuristic {
|
|||
}
|
||||
|
||||
void setGotNothing(Inverter<> *iv) {
|
||||
if(RF_NA != mStoredIdx) {
|
||||
// if communication fails on first try with temporarily good level, revert it back to its original level
|
||||
iv->txRfQuality[iv->txRfChId] = mStoredIdx;
|
||||
mStoredIdx = RF_NA;
|
||||
}
|
||||
|
||||
if(!mTestEn) {
|
||||
updateQuality(iv, -2); // BAD
|
||||
mTestEn = true;
|
||||
iv->txRfChId = mCycle % RF_MAX_CHANNEL_ID;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -100,13 +110,14 @@ class Heuristic {
|
|||
case 3: return 61;
|
||||
case 4: return 75;
|
||||
}
|
||||
return 0; // standard
|
||||
return 3; // standard
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t mChList[5] = {03, 23, 40, 61, 75};
|
||||
bool mTestEn = false;
|
||||
uint8_t mCycle = 0;
|
||||
uint8_t mTestIdx = 0;
|
||||
int8_t mStoredIdx = RF_NA;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -34,12 +34,13 @@ class HmRadio : public Radio {
|
|||
}
|
||||
~HmRadio() {}
|
||||
|
||||
void setup(bool *serialDebug, bool *privacyMode, uint8_t irq = IRQ_PIN, uint8_t ce = CE_PIN, uint8_t cs = CS_PIN, uint8_t sclk = SCLK_PIN, uint8_t mosi = MOSI_PIN, uint8_t miso = MISO_PIN) {
|
||||
void setup(bool *serialDebug, bool *privacyMode, bool *printWholeTrace, uint8_t irq = IRQ_PIN, uint8_t ce = CE_PIN, uint8_t cs = CS_PIN, uint8_t sclk = SCLK_PIN, uint8_t mosi = MOSI_PIN, uint8_t miso = MISO_PIN) {
|
||||
DPRINTLN(DBG_VERBOSE, F("hmRadio.h:setup"));
|
||||
pinMode(irq, INPUT_PULLUP);
|
||||
|
||||
mSerialDebug = serialDebug;
|
||||
mPrivacyMode = privacyMode;
|
||||
mPrintWholeTrace = printWholeTrace;
|
||||
|
||||
if(*mSerialDebug) {
|
||||
DPRINT(DBG_VERBOSE, F("hmRadio.h : HmRadio():mNrf24(CE_PIN: "));
|
||||
|
@ -293,10 +294,13 @@ class HmRadio : public Radio {
|
|||
DBGPRINT(" CH");
|
||||
DBGPRINT(String(mTxChIdx));
|
||||
DBGPRINT(F(" | "));
|
||||
if(*mPrintWholeTrace) {
|
||||
if(*mPrivacyMode)
|
||||
ah::dumpBuf(mTxBuf, len, 1, 4);
|
||||
else
|
||||
ah::dumpBuf(mTxBuf, len);
|
||||
} else
|
||||
DBGHEXLN(mTxBuf[9]);
|
||||
}
|
||||
|
||||
mNrf24.stopListening();
|
||||
|
|
|
@ -111,8 +111,7 @@ class Radio {
|
|||
|
||||
uint32_t mDtuSn;
|
||||
volatile bool mIrqRcvd;
|
||||
bool *mSerialDebug;
|
||||
bool *mPrivacyMode;
|
||||
bool *mSerialDebug, *mPrivacyMode, *mPrintWholeTrace;
|
||||
uint8_t mTxBuf[MAX_RF_PAYLOAD_SIZE];
|
||||
|
||||
};
|
||||
|
|
|
@ -19,11 +19,12 @@ class CmtRadio : public Radio {
|
|||
mCmtAvail = false;
|
||||
}
|
||||
|
||||
void setup(bool *serialDebug, bool *privacyMode, uint8_t pinSclk, uint8_t pinSdio, uint8_t pinCsb, uint8_t pinFcsb, bool genDtuSn = true) {
|
||||
void setup(bool *serialDebug, bool *privacyMode, bool *printWholeTrace, uint8_t pinSclk, uint8_t pinSdio, uint8_t pinCsb, uint8_t pinFcsb, bool genDtuSn = true) {
|
||||
mCmt.setup(pinSclk, pinSdio, pinCsb, pinFcsb);
|
||||
reset(genDtuSn);
|
||||
mPrivacyMode = privacyMode;
|
||||
mSerialDebug = serialDebug;
|
||||
mPrintWholeTrace = printWholeTrace;
|
||||
}
|
||||
|
||||
void setup(bool *serialDebug, bool *privacyMode, bool genDtuSn = true) {
|
||||
|
@ -97,10 +98,13 @@ class CmtRadio : public Radio {
|
|||
DBGPRINT(F("TX "));
|
||||
DBGPRINT(String(mCmt.getFreqKhz()/1000.0f));
|
||||
DBGPRINT(F("Mhz | "));
|
||||
if(*mPrintWholeTrace) {
|
||||
if(*mPrivacyMode)
|
||||
ah::dumpBuf(mTxBuf, len, 1, 4);
|
||||
else
|
||||
ah::dumpBuf(mTxBuf, len);
|
||||
} else
|
||||
DBGHEXLN(mTxBuf[9]);
|
||||
}
|
||||
|
||||
uint8_t status = mCmt.tx(mTxBuf, len);
|
||||
|
|
|
@ -563,6 +563,7 @@ class RestApi {
|
|||
obj[F("show_live_data")] = mConfig->serial.showIv;
|
||||
obj[F("debug")] = mConfig->serial.debug;
|
||||
obj[F("priv")] = mConfig->serial.privacyLog;
|
||||
obj[F("wholeTrace")] = mConfig->serial.printWholeTrace;
|
||||
}
|
||||
|
||||
void getStaticIp(JsonObject obj) {
|
||||
|
|
|
@ -52,6 +52,10 @@
|
|||
<div class="col-8 col-sm-3">Privacy Mode</div>
|
||||
<div class="col-4 col-sm-9"><input type="checkbox" name="priv"/></div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col-8 col-sm-3">Print whole traces in Log</div>
|
||||
<div class="col-4 col-sm-9"><input type="checkbox" name="wholeTrace"/></div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
|
@ -937,7 +941,7 @@
|
|||
/*ENDIF_ESP32*/
|
||||
|
||||
function parseSerial(obj) {
|
||||
for(var i of [["serEn", "show_live_data"], ["serDbg", "debug"], ["priv", "priv"]])
|
||||
for(var i of [["serEn", "show_live_data"], ["serDbg", "debug"], ["priv", "priv"], ["wholeTrace", "wholeTrace"]])
|
||||
document.getElementsByName(i[0])[0].checked = obj[i[1]];
|
||||
}
|
||||
|
||||
|
|
|
@ -560,6 +560,7 @@ class Web {
|
|||
// serial console
|
||||
mConfig->serial.debug = (request->arg("serDbg") == "on");
|
||||
mConfig->serial.privacyLog = (request->arg("priv") == "on");
|
||||
mConfig->serial.printWholeTrace = (request->arg("wholeTrace") == "on");
|
||||
mConfig->serial.showIv = (request->arg("serEn") == "on");
|
||||
|
||||
// display
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue