From 88f5120fc0d2cd2b1f7c40ca56bc49c52af7e79d Mon Sep 17 00:00:00 2001 From: rejoe2 Date: Thu, 30 Mar 2023 13:58:22 +0200 Subject: [PATCH 01/10] MI - restructure priority handling - app differenciates between HM and MI type now (thx to beegee3 and AsZork) - review debug output (also for HM) --- src/app.h | 8 ++- src/hm/hmPayload.h | 31 +++++----- src/hm/miPayload.h | 138 +++++++++++++++++++++++++-------------------- 3 files changed, 99 insertions(+), 78 deletions(-) diff --git a/src/app.h b/src/app.h index cbf7e6a1..069f3c7d 100644 --- a/src/app.h +++ b/src/app.h @@ -141,8 +141,12 @@ class app : public IApp, public ah::Scheduler { } void ivSendHighPrio(Inverter<> *iv) { - if(mIVCommunicationOn) // only send commands if communcation is enabled - mPayload.ivSendHighPrio(iv); + if(mIVCommunicationOn) { // only send commands if communcation is enabled + if (iv->ivGen == IV_HM) + mPayload.ivSendHighPrio(iv); + else if (iv->ivGen == IV_MI) + mMiPayload.ivSendHighPrio(iv); + } } bool getMqttIsConnected() { diff --git a/src/hm/hmPayload.h b/src/hm/hmPayload.h index 0af8f466..ff555c33 100644 --- a/src/hm/hmPayload.h +++ b/src/hm/hmPayload.h @@ -64,7 +64,7 @@ class HmPayload { } void loop() { - if(NULL != mHighPrioIv) { + if ( NULL != mHighPrioIv && mHighPrioIv->ivGen == IV_HM ) { ivSend(mHighPrioIv, true); mHighPrioIv = NULL; } @@ -110,19 +110,22 @@ class HmPayload { process(false); // no retransmit if (!mPayload[iv->id].complete) { - if (MAX_PAYLOAD_ENTRIES == mPayload[iv->id].maxPackId) - mStat->rxFailNoAnser++; // got nothing - else - mStat->rxFail++; // got fragments but not complete response - - iv->setQueuedCmdFinished(); // command failed - if (mSerialDebug) { - DPRINTLN(DBG_INFO, F("enqueued cmd failed/timeout")); + if (mSerialDebug) DPRINT_IVID(DBG_INFO, iv->id); - DBGPRINT(F("no Payload received! (retransmits: ")); - DBGPRINT(String(mPayload[iv->id].retransmits)); - DBGPRINTLN(F(")")); + if (MAX_PAYLOAD_ENTRIES == mPayload[iv->id].maxPackId) { + mStat->rxFailNoAnser++; // got nothing + if (mSerialDebug) + DBGPRINTLN(F("enqueued cmd failed/timeout")); } + else { + mStat->rxFail++; // got fragments but not complete response + if (mSerialDebug) { + DBGPRINT(F("no complete Payload received! (retransmits: ")); + DBGPRINT(String(mPayload[iv->id].retransmits)); + DBGPRINTLN(F(")")); + } + } + iv->setQueuedCmdFinished(); // command failed } } } @@ -390,8 +393,8 @@ class HmPayload { } void reset(uint8_t id) { - DPRINT(DBG_INFO, "resetPayload: id: "); - DBGPRINTLN(String(id)); + DPRINT_IVID(DBG_INFO, id); + DBGPRINTLN(F("resetPayload")); memset(mPayload[id].len, 0, MAX_PAYLOAD_ENTRIES); mPayload[id].txCmd = 0; mPayload[id].gotFragment = false; diff --git a/src/hm/miPayload.h b/src/hm/miPayload.h index dbe43c06..79bae081 100644 --- a/src/hm/miPayload.h +++ b/src/hm/miPayload.h @@ -25,7 +25,6 @@ typedef struct { uint8_t txId; uint8_t invId; uint8_t retransmits; - //uint8_t skipfirstrepeat; bool gotFragment; /* uint8_t data[MAX_PAYLOAD_ENTRIES][MAX_RF_PAYLOAD_SIZE]; @@ -70,8 +69,8 @@ class MiPayload { } void loop() { - if(NULL != mHighPrioIv) { // && mHighPrioIv->ivGen == IV_MI) { - ivSend(mHighPrioIv, true); // for devcontrol commands? + if ( NULL != mHighPrioIv && mHighPrioIv->ivGen == IV_MI ) { + ivSend(mHighPrioIv, true); // for e.g. devcontrol commands mHighPrioIv = NULL; } } @@ -87,21 +86,23 @@ class MiPayload { process(false); // no retransmit if (!mPayload[iv->id].complete) { - if (!mPayload[iv->id].gotFragment) - mStat->rxFailNoAnser++; // got nothing - else - mStat->rxFail++; // got fragments but not complete response - - iv->setQueuedCmdFinished(); // command failed if (mSerialDebug) DPRINT_IVID(DBG_INFO, iv->id); - DBGPRINTLN(F("enqueued cmd failed/timeout")); - if (mSerialDebug) { - DPRINT_IVID(DBG_INFO, iv->id); - DBGPRINT(F("no Payload received! (retransmits: ")); - DBGPRINT(String(mPayload[iv->id].retransmits)); - DBGPRINTLN(F(")")); + if (!mPayload[iv->id].gotFragment) { + mStat->rxFailNoAnser++; // got nothing + if (mSerialDebug) + DBGPRINTLN(F("enqueued cmd failed/timeout")); } + else { + mStat->rxFail++; // got "fragments" (part of the required messages) + // but no complete set of responses + if (mSerialDebug) { + DBGPRINT(F("no complete Payload received! (retransmits: ")); + DBGPRINT(String(mPayload[iv->id].retransmits)); + DBGPRINTLN(F(")")); + } + } + iv->setQueuedCmdFinished(); // command failed } } } @@ -232,42 +233,39 @@ const byteAssign_t InfoAssignment[] = { iv->setValue(i, rec, (float) ((p->packet[(12+2*i)] << 8) + p->packet[(13+2*i)])/1); } iv->isConnected = true; + mPayload[iv->id].gotFragment = true; if(mSerialDebug) { DPRINT_IVID(DBG_INFO, iv->id); DPRINT(DBG_INFO,F("HW_VER is ")); DBGPRINTLN(String((p->packet[24] << 8) + p->packet[25])); } - /*iv->setQueuedCmdFinished(); - mSys->Radio.sendCmdPacket(iv->radioId.u64, 0x0f, 0x01, false);*/ } else if ( p->packet[9] == 0x01 || p->packet[9] == 0x10 ) {//second frame for MI, 3rd gen. answers in 0x10 DPRINT_IVID(DBG_INFO, iv->id); if ( p->packet[9] == 0x01 ) { DBGPRINTLN(F("got 2nd frame (hw info)")); - } else { - DBGPRINTLN(F("3rd gen. inverter!")); // see table in OpenDTU code, DevInfoParser.cpp devInfo[] - } - // xlsx: HW_ECapValue is total energy?!? (data coll. inst. #154) - 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((p->packet[12] << 8) + p->packet[13])); - if ( p->packet[9] == 0x01 ) { + 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; 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_ECapValue ")); - DBGPRINTLN(String((p->packet[20] << 8) + p->packet[21])); - DPRINT(DBG_INFO,F("HW_FB_TLmValue ")); DBGPRINTLN(String((p->packet[14] << 8) + p->packet[15])); DPRINT(DBG_INFO,F("HW_FB_ReSPRT ")); DBGPRINTLN(String((p->packet[16] << 8) + p->packet[17])); DPRINT(DBG_INFO,F("HW_GridSamp_ResValule ")); DBGPRINTLN(String((p->packet[18] << 8) + p->packet[19])); + DPRINT(DBG_INFO,F("HW_ECapValue ")); + DBGPRINTLN(String((p->packet[20] << 8) + p->packet[21])); } + } else { + DBGPRINTLN(F("3rd gen. inverter!")); // see table in OpenDTU code, DevInfoParser.cpp devInfo[] } + } else if ( p->packet[9] == 0x12 ) {//3rd frame DPRINT_IVID(DBG_INFO, iv->id); DBGPRINTLN(F("got 3rd frame (hw info)")); iv->setQueuedCmdFinished(); + mPayload[iv->id].complete = true; mStat->rxSuccess++; } @@ -347,7 +345,9 @@ const byteAssign_t InfoAssignment[] = { payloadLen -= 2; if (mSerialDebug) { - DPRINT(DBG_INFO, F("Payload (") + String(payloadLen) + "): "); + DPRINT(DBG_INFO, F("Payload (")); + DBGPRINT(String(payloadLen)); + DBGPRINT("): "); mSys->Radio.dumpBuf(payload, payloadLen); } @@ -448,8 +448,8 @@ const byteAssign_t InfoAssignment[] = { } else { bool change = false; if ( cmd >= 0x36 && cmd < 0x39 ) { // MI-1500 Data command - //cmd++; // just request the next channel - //change = true; + if (cmd > 0x36 && mPayload[iv->id].retransmits==1) // first request for the upper channels + change = true; } else if ( cmd == 0x09 ) {//MI single or dual channel device if ( mPayload[iv->id].dataAB[CH1] && iv->type == INV_TYPE_2CH ) { if (!mPayload[iv->id].stsAB[CH1] && mPayload[iv->id].retransmits<2) {} @@ -641,7 +641,6 @@ const byteAssign_t InfoAssignment[] = { ( p->packet[0] == 0x91 || p->packet[0] == (0x37 + ALL_FRAMES) ) ? CH2 : p->packet[0] == (0x38 + ALL_FRAMES) ? CH3 : CH4; - //DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") data msg 0x") + String(p->packet[0], HEX) + F(" channel ") + datachan); // count in RF_communication_protocol.xlsx is with offset = -1 iv->setValue(iv->getPosByChFld(datachan, FLD_UDC, rec), rec, (float)((p->packet[9] << 8) + p->packet[10])/10); yield(); @@ -656,7 +655,6 @@ const byteAssign_t InfoAssignment[] = { yield(); iv->setValue(iv->getPosByChFld(0, FLD_T, rec), rec, (float) ((int16_t)(p->packet[21] << 8) + p->packet[22])/10); iv->setValue(iv->getPosByChFld(0, FLD_IRR, rec), rec, (float) (calcIrradiation(iv, datachan))); - //AC Power is missing; we may have to calculate, as no respective data is in payload if ( datachan < 3 ) { mPayload[iv->id].dataAB[datachan] = true; @@ -687,17 +685,13 @@ const byteAssign_t InfoAssignment[] = { mSys->Radio.prepareDevInformCmd(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex, false, cmd); mPayload[iv->id].txCmd = cmd;*/ mPayload[iv->id].txCmd++; - if (mPayload[iv->id].retransmits) - mPayload[iv->id].retransmits--; // reserve retransmissions for each response + mPayload[iv->id].retransmits = 0; // reserve retransmissions for each response mPayload[iv->id].complete = false; } - else 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); - mPayload[iv->id].txCmd = cmd;*/ + /*else if ( p->packet[0] == (0x39 + ALL_FRAMES) ) { mPayload[iv->id].complete = true; - } + }*/ /*if (iv->alarmMesIndex < rec->record[iv->getPosByChFld(0, FLD_EVT, rec)]){ iv->alarmMesIndex = rec->record[iv->getPosByChFld(0, FLD_EVT, rec)]; @@ -709,35 +703,34 @@ const byteAssign_t InfoAssignment[] = { } - if ( mPayload[iv->id].complete || //4ch device - (iv->type != INV_TYPE_4CH //other devices + /* + if(AlarmData == mPayload[iv->id].txCmd) { + uint8_t i = 0; + uint16_t code; + uint32_t start, end; + while(1) { + code = iv->parseAlarmLog(i++, payload, payloadLen, &start, &end); + if(0 == code) + break; + if (NULL != mCbMiAlarm) + (mCbAlarm)(code, start, end); + yield(); + } + }*/ + + //if ( mPayload[iv->id].complete || //4ch device + if ( p->packet[0] == (0x39 + ALL_FRAMES) || //4ch device - last message + (iv->type != INV_TYPE_4CH //other devices && mPayload[iv->id].dataAB[CH0] && mPayload[iv->id].stsAB[CH0])) { miComplete(iv); } - - - -/* - if(AlarmData == mPayload[iv->id].txCmd) { - uint8_t i = 0; - uint16_t code; - uint32_t start, end; - while(1) { - code = iv->parseAlarmLog(i++, payload, payloadLen, &start, &end); - if(0 == code) - break; - if (NULL != mCbMiAlarm) - (mCbAlarm)(code, start, end); - yield(); - } - }*/ } void miComplete(Inverter<> *iv) { - if (mPayload[iv->id].complete) - return; //if we got second message as well in repreated attempt - mPayload[iv->id].complete = true; // For 2 CH devices, this might be too short... + if ( mPayload[iv->id].complete ) // && iv->type != INV_TYPE_4CH) + return; // if we got second message as well in repreated attempt + mPayload[iv->id].complete = true; DPRINT_IVID(DBG_INFO, iv->id); DBGPRINTLN(F("got all msgs")); record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); @@ -778,6 +771,27 @@ const byteAssign_t InfoAssignment[] = { return true; } +/* uint16_t mParseAlarmLog(uint8_t id, uint8_t pyld[], uint8_t len, uint32_t *start, uint32_t *endTime) { + uint8_t startOff = 2 + id * ALARM_LOG_ENTRY_SIZE; + if((startOff + ALARM_LOG_ENTRY_SIZE) > len) + return 0; + + uint16_t wCode = ((uint16_t)pyld[startOff]) << 8 | pyld[startOff+1]; + uint32_t startTimeOffset = 0, endTimeOffset = 0; + + if (((wCode >> 13) & 0x01) == 1) // check if is AM or PM + startTimeOffset = 12 * 60 * 60; + if (((wCode >> 12) & 0x01) == 1) // check if is AM or PM + endTimeOffset = 12 * 60 * 60; + + *start = (((uint16_t)pyld[startOff + 4] << 8) | ((uint16_t)pyld[startOff + 5])) + startTimeOffset; + *endTime = (((uint16_t)pyld[startOff + 6] << 8) | ((uint16_t)pyld[startOff + 7])) + endTimeOffset; + + DPRINTLN(DBG_INFO, "Alarm #" + String(pyld[startOff+1]) + " '" + String(getAlarmStr(pyld[startOff+1])) + "' start: " + ah::getTimeStr(*start) + ", end: " + ah::getTimeStr(*endTime)); + return pyld[startOff+1]; + } +*/ + void reset(uint8_t id, bool clrSts = false) { DPRINT_IVID(DBG_INFO, id); DBGPRINTLN(F("resetPayload")); From f4accf1e373049778df6dbc7746d21a718453f52 Mon Sep 17 00:00:00 2001 From: rejoe2 Date: Thu, 30 Mar 2023 19:44:08 +0200 Subject: [PATCH 02/10] MI - find priority inverter remove unnecessary type checks --- src/hm/hmPayload.h | 2 +- src/hm/miPayload.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hm/hmPayload.h b/src/hm/hmPayload.h index ff555c33..de99d41b 100644 --- a/src/hm/hmPayload.h +++ b/src/hm/hmPayload.h @@ -64,7 +64,7 @@ class HmPayload { } void loop() { - if ( NULL != mHighPrioIv && mHighPrioIv->ivGen == IV_HM ) { + if (NULL != mHighPrioIv) { ivSend(mHighPrioIv, true); mHighPrioIv = NULL; } diff --git a/src/hm/miPayload.h b/src/hm/miPayload.h index 79bae081..fd2665f8 100644 --- a/src/hm/miPayload.h +++ b/src/hm/miPayload.h @@ -69,7 +69,7 @@ class MiPayload { } void loop() { - if ( NULL != mHighPrioIv && mHighPrioIv->ivGen == IV_MI ) { + if (NULL != mHighPrioIv) { ivSend(mHighPrioIv, true); // for e.g. devcontrol commands mHighPrioIv = NULL; } From 1f0f8b904a57ff162b67992c3090b295c8dddf26 Mon Sep 17 00:00:00 2001 From: rejoe2 Date: Fri, 31 Mar 2023 08:06:51 +0200 Subject: [PATCH 03/10] MI - use only crc8 for MI commands MI-600 at least sents answers as well... --- src/hm/hmRadio.h | 11 ++++++----- src/hm/miPayload.h | 4 ++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h index c37ab7d0..3917df8e 100644 --- a/src/hm/hmRadio.h +++ b/src/hm/hmRadio.h @@ -205,6 +205,7 @@ class HmRadio { } else { //MI 2nd gen. specific switch (cmd) { case TurnOn: + //mTxBuf[0] = 0x50; mTxBuf[9] = 0x55; mTxBuf[10] = 0xaa; break; @@ -223,7 +224,7 @@ class HmRadio { } cnt++; } - sendPacket(invId, cnt, isRetransmit, true); + sendPacket(invId, 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. @@ -239,9 +240,9 @@ class HmRadio { sendPacket(invId, 24, isRetransmit, true); } - void sendCmdPacket(uint64_t invId, uint8_t mid, uint8_t pid, bool isRetransmit) { + void sendCmdPacket(uint64_t invId, uint8_t mid, uint8_t pid, bool isRetransmit, bool isMI=false) { initPacket(invId, mid, pid); - sendPacket(invId, 10, isRetransmit, false); + sendPacket(invId, 10, isRetransmit, isMI); } void dumpBuf(uint8_t buf[], uint8_t len) { @@ -317,12 +318,12 @@ class HmRadio { mTxBuf[9] = pid; } - void sendPacket(uint64_t invId, uint8_t len, bool isRetransmit, bool clear=false) { + void sendPacket(uint64_t invId, uint8_t len, bool isRetransmit, bool appendCrc16=false) { //DPRINTLN(DBG_VERBOSE, F("hmRadio.h:sendPacket")); //DPRINTLN(DBG_VERBOSE, "sent packet: #" + String(mSendCnt)); // append crc's - if (len > 10) { + if (appendCrc16 && len > 10) { // crc control data uint16_t crc = ah::crc16(&mTxBuf[10], len - 10); mTxBuf[len++] = (crc >> 8) & 0xff; diff --git a/src/hm/miPayload.h b/src/hm/miPayload.h index fd2665f8..d9f0b338 100644 --- a/src/hm/miPayload.h +++ b/src/hm/miPayload.h @@ -149,7 +149,7 @@ 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); + mSys->Radio.sendCmdPacket(iv->radioId.u64, cmd, cmd2, false, true); } else { mSys->Radio.prepareDevInformCmd(iv->radioId.u64, cmd2, mPayload[iv->id].ts, iv->alarmMesIndex, false, cmd); }; @@ -442,7 +442,7 @@ 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); + mSys->Radio.sendCmdPacket(iv->radioId.u64, 0x0f, 0x00, true, true); //iv->setQueuedCmdFinished(); //cmd = iv->getQueuedCmd(); } else { From 24bfb43b02c8b6b86d18838656307ec2741df2a7 Mon Sep 17 00:00:00 2001 From: rejoe2 Date: Fri, 31 Mar 2023 19:17:16 +0200 Subject: [PATCH 04/10] Radio changes, MQTT fixes * consolidated (?) proposals from beegee3 * timing now 410microsesonds --- src/app.cpp | 2 + src/hm/hmRadio.h | 82 ++++++++++++++++++----------------------- src/hm/miPayload.h | 4 +- src/publisher/pubMqtt.h | 11 +++++- 4 files changed, 50 insertions(+), 49 deletions(-) diff --git a/src/app.cpp b/src/app.cpp index d3fba12a..7d9f75ba 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -51,6 +51,7 @@ void app::setup() { mMiPayload.setup(this, &mSys, &mStat, mConfig->nrf.maxRetransPerPyld, &mTimestamp); mMiPayload.enableSerialDebug(mConfig->serial.debug); + mMiPayload.addPayloadListener(std::bind(&app::payloadEventListener, this, std::placeholders::_1)); // DBGPRINTLN("--- after payload"); // DBGPRINTLN(String(ESP.getFreeHeap())); @@ -67,6 +68,7 @@ void app::setup() { mMqtt.setup(&mConfig->mqtt, mConfig->sys.deviceName, mVersion, &mSys, &mTimestamp); mMqtt.setSubscriptionCb(std::bind(&app::mqttSubRxCb, this, std::placeholders::_1)); mPayload.addAlarmListener(std::bind(&PubMqttType::alarmEventListener, &mMqtt, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); + mMiPayload.addAlarmListener(std::bind(&PubMqttType::alarmEventListener, &mMqtt, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); } #endif setupLed(); diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h index 3917df8e..8a4f602e 100644 --- a/src/hm/hmRadio.h +++ b/src/hm/hmRadio.h @@ -101,19 +101,20 @@ class HmRadio { // change the byte order of the DTU serial number and append the required 0x01 at the end DTU_RADIO_ID = ((uint64_t)(((dtuSn >> 24) & 0xFF) | ((dtuSn >> 8) & 0xFF00) | ((dtuSn << 8) & 0xFF0000) | ((dtuSn << 24) & 0xFF000000)) << 8) | 0x01; + SPIClass* spi; #ifdef ESP32 #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 - mSpi = new SPIClass(FSPI); + spi = new SPIClass(FSPI); #else - mSpi = new SPIClass(VSPI); + spi = new SPIClass(VSPI); #endif - mSpi->begin(sclk, miso, mosi, cs); + spi->begin(sclk, miso, mosi, cs); #else //the old ESP82xx cannot freely place their SPI pins - mSpi = new SPIClass(); - mSpi->begin(); + spi = new SPIClass(); + spi->begin(); #endif - mNrf24.begin(mSpi, ce, cs); + mNrf24.begin(spi, ce, cs); mNrf24.setRetries(3, 15); // 3*250us + 250us and 15 loops -> 15ms mNrf24.setChannel(mRfChLst[mRxChIdx]); @@ -123,7 +124,7 @@ class HmRadio { mNrf24.enableDynamicPayloads(); mNrf24.setCRCLength(RF24_CRC_16); mNrf24.setAddressWidth(5); - mNrf24.openReadingPipe(1, DTU_RADIO_ID); + mNrf24.openReadingPipe(1, reinterpret_cast(&DTU_RADIO_ID)); // enable all receiving interrupts mNrf24.maskIRQ(false, false, false); @@ -147,32 +148,31 @@ class HmRadio { bool tx_ok, tx_fail, rx_ready; mNrf24.whatHappened(tx_ok, tx_fail, rx_ready); // resets the IRQ pin to HIGH mNrf24.flush_tx(); // empty TX FIFO - //DBGPRINTLN("TX whatHappened Ch" + String(mRfChLst[mTxChIdx]) + " " + String(tx_ok) + String(tx_fail) + String(rx_ready)); - // start listening on the default RX channel - mRxChIdx = 0; + // start listening mNrf24.setChannel(mRfChLst[mRxChIdx]); mNrf24.startListening(); - //uint32_t debug_ms = millis(); - uint16_t cnt = 300; // that is 60 times 5 channels - while (0 < cnt--) { - uint32_t startMillis = millis(); - while (millis()-startMillis < 4) { // listen 4ms to each channel + uint32_t startMicros = micros(); + uint32_t loopMillis = millis(); + while (millis()-loopMillis < 410) { + while (micros()-startMicros < 5110) { // listen 5110us to each channel if (mIrqRcvd) { mIrqRcvd = false; if (getReceived()) { // everything received - //DBGPRINTLN("RX finished Cnt: " + String(300-cnt) + " time used: " + String(millis()-debug_ms)+ " ms"); return true; } } yield(); } - switchRxCh(); // switch to next RX channel + // switch to next RX channel + startMicros = micros(); + if(++mRxChIdx >= RF_CHANNELS) + mRxChIdx = 0; + mNrf24.setChannel(mRfChLst[mRxChIdx]); yield(); } // not finished but time is over - //DBGPRINTLN("RX not finished: 300 time used: " + String(millis()-debug_ms)+ " ms"); return true; } @@ -240,9 +240,9 @@ class HmRadio { sendPacket(invId, 24, isRetransmit, true); } - void sendCmdPacket(uint64_t invId, uint8_t mid, uint8_t pid, bool isRetransmit, bool isMI=false) { + void sendCmdPacket(uint64_t invId, uint8_t mid, uint8_t pid, bool isRetransmit, bool appendCrc16=true) { initPacket(invId, mid, pid); - sendPacket(invId, 10, isRetransmit, isMI); + sendPacket(invId, 10, isRetransmit, appendCrc16); } void dumpBuf(uint8_t buf[], uint8_t len) { @@ -275,7 +275,6 @@ class HmRadio { bool getReceived(void) { bool tx_ok, tx_fail, rx_ready; mNrf24.whatHappened(tx_ok, tx_fail, rx_ready); // resets the IRQ pin to HIGH - //DBGPRINTLN("RX whatHappened Ch" + String(mRfChLst[mRxChIdx]) + " " + String(tx_ok) + String(tx_fail) + String(rx_ready)); bool isLastPackage = false; while(mNrf24.available()) { @@ -286,29 +285,21 @@ class HmRadio { p.ch = mRfChLst[mRxChIdx]; p.len = len; mNrf24.read(p.packet, len); - mBufCtrl.push(p); - if (p.packet[0] == (TX_REQ_INFO + ALL_FRAMES)) // response from get information command - isLastPackage = (p.packet[9] > 0x81); // > 0x81 indicates last packet received - else if (p.packet[0] == ( 0x0f + ALL_FRAMES) ) // response from MI get information command - isLastPackage = (p.packet[9] > 0x11); // > 0x11 indicates last packet received - else if (p.packet[0] != 0x00 && p.packet[0] != 0x88 && p.packet[0] != 0x92) - // ignore fragment number zero and MI status messages - isLastPackage = true; // response from dev control command - yield(); + if (p.packet[0] != 0x00) { + mBufCtrl.push(p); + if (p.packet[0] == (TX_REQ_INFO + ALL_FRAMES)) // response from get information command + isLastPackage = (p.packet[9] > ALL_FRAMES); // > ALL_FRAMES indicates last packet received + else if (p.packet[0] == ( 0x0f + ALL_FRAMES) ) // response from MI get information command + isLastPackage = (p.packet[9] > 0x10); // > 0x10 indicates last packet received + else if ((p.packet[0] != 0x88) && (p.packet[0] != 0x92)) // ignore fragment number zero and MI status messages //#0 was p.packet[0] != 0x00 && + isLastPackage = true; // response from dev control command + } } + yield(); } return isLastPackage; } - void switchRxCh() { - mNrf24.stopListening(); - // get next channel index - if(++mRxChIdx >= RF_CHANNELS) - mRxChIdx = 0; - mNrf24.setChannel(mRfChLst[mRxChIdx]); - mNrf24.startListening(); - } - void initPacket(uint64_t invId, uint8_t mid, uint8_t pid) { DPRINTLN(DBG_VERBOSE, F("initPacket, mid: ") + String(mid, HEX) + F(" pid: ") + String(pid, HEX)); memset(mTxBuf, 0, MAX_RF_PAYLOAD_SIZE); @@ -318,12 +309,12 @@ class HmRadio { mTxBuf[9] = pid; } - void sendPacket(uint64_t invId, uint8_t len, bool isRetransmit, bool appendCrc16=false) { + void sendPacket(uint64_t invId, uint8_t len, bool isRetransmit, bool appendCrc16=true) { //DPRINTLN(DBG_VERBOSE, F("hmRadio.h:sendPacket")); //DPRINTLN(DBG_VERBOSE, "sent packet: #" + String(mSendCnt)); // append crc's - if (appendCrc16 && len > 10) { + if (appendCrc16 && (len > 10)) { // crc control data uint16_t crc = ah::crc16(&mTxBuf[10], len - 10); mTxBuf[len++] = (crc >> 8) & 0xff; @@ -333,6 +324,10 @@ class HmRadio { mTxBuf[len] = ah::crc8(mTxBuf, len); len++; + // set TX and RX channels + mTxChIdx = (mTxChIdx + 1) % RF_CHANNELS; + mRxChIdx = (mTxChIdx + 2) % RF_CHANNELS; + if(mSerialDebug) { DPRINT(DBG_INFO, F("TX ")); DBGPRINT(String(len)); @@ -347,10 +342,6 @@ class HmRadio { mNrf24.openWritingPipe(reinterpret_cast(&invId)); mNrf24.startWrite(mTxBuf, len, false); // false = request ACK response - // switch TX channel for next packet - if(++mTxChIdx >= RF_CHANNELS) - mTxChIdx = 0; - if(isRetransmit) mRetransmits++; else @@ -364,7 +355,6 @@ class HmRadio { uint8_t mTxChIdx; uint8_t mRxChIdx; - SPIClass* mSpi; RF24 mNrf24; uint8_t mTxBuf[MAX_RF_PAYLOAD_SIZE]; }; diff --git a/src/hm/miPayload.h b/src/hm/miPayload.h index d9f0b338..92020b51 100644 --- a/src/hm/miPayload.h +++ b/src/hm/miPayload.h @@ -149,7 +149,7 @@ 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, true); + mSys->Radio.sendCmdPacket(iv->radioId.u64, cmd, cmd2, false, false); } else { mSys->Radio.prepareDevInformCmd(iv->radioId.u64, cmd2, mPayload[iv->id].ts, iv->alarmMesIndex, false, cmd); }; @@ -442,7 +442,7 @@ 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, true); + mSys->Radio.sendCmdPacket(iv->radioId.u64, 0x0f, 0x00, true, false); //iv->setQueuedCmdFinished(); //cmd = iv->getQueuedCmd(); } else { diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index b008d8d2..f75c4068 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -49,6 +49,8 @@ class PubMqtt { mTxCnt = 0; mSubscriptionCb = NULL; memset(mLastIvState, MQTT_STATUS_NOT_AVAIL_NOT_PROD, MAX_NUM_INVERTERS); + memset(mIvLastRTRpub, 0, MAX_NUM_INVERTERS * 4); + mLastAnyAvail = false; } @@ -522,7 +524,13 @@ class PubMqtt { void sendData(Inverter<> *iv, uint8_t curInfoCmd) { record_t<> *rec = iv->getRecordStruct(curInfoCmd); - if (iv->getLastTs(rec) > 0) { + uint32_t lastTs = iv->getLastTs(rec); + bool pubData = (lastTs > 0); + if (curInfoCmd == RealTimeRunData_Debug) + pubData &= (lastTs != mIvLastRTRpub[iv->id]); + + if (pubData) { + mIvLastRTRpub[iv->id] = lastTs; for (uint8_t i = 0; i < rec->length; i++) { bool retained = false; if (curInfoCmd == RealTimeRunData_Debug) { @@ -653,6 +661,7 @@ class PubMqtt { subscriptionCb mSubscriptionCb; bool mLastAnyAvail; uint8_t mLastIvState[MAX_NUM_INVERTERS]; + uint32_t mIvLastRTRpub[MAX_NUM_INVERTERS]; uint16_t mIntervalTimeout; // last will topic and payload must be available trough lifetime of 'espMqttClient' From e8e216cd6998c06f9d2315c6a64ff30cb8b1f99c Mon Sep 17 00:00:00 2001 From: rejoe2 Date: Sat, 1 Apr 2023 19:04:47 +0200 Subject: [PATCH 05/10] MI - fix MQTT version + changed rx/tx logic (times + debug output) --- src/hm/hmRadio.h | 9 +++++++-- src/hm/miPayload.h | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h index 8a4f602e..c1152e32 100644 --- a/src/hm/hmRadio.h +++ b/src/hm/hmRadio.h @@ -155,10 +155,14 @@ class HmRadio { uint32_t startMicros = micros(); uint32_t loopMillis = millis(); - while (millis()-loopMillis < 410) { - while (micros()-startMicros < 5110) { // listen 5110us to each channel + + uint32_t timeslot = 4088;//5110; //3066; //6132;//4088; + uint64_t tsCnt = 0; + while (millis()-loopMillis < 200) { + while (micros()-startMicros < timeslot) { // listen timeslot us to each channel if (mIrqRcvd) { mIrqRcvd = false; + DBGPRINTLN("*** time: " + String(tsCnt*(uint64_t)timeslot + (uint64_t)(micros()-startMicros)) + " ***"); if (getReceived()) { // everything received return true; } @@ -170,6 +174,7 @@ class HmRadio { if(++mRxChIdx >= RF_CHANNELS) mRxChIdx = 0; mNrf24.setChannel(mRfChLst[mRxChIdx]); + tsCnt++; yield(); } // not finished but time is over diff --git a/src/hm/miPayload.h b/src/hm/miPayload.h index 92020b51..17d26fe8 100644 --- a/src/hm/miPayload.h +++ b/src/hm/miPayload.h @@ -751,7 +751,7 @@ const byteAssign_t InfoAssignment[] = { iv->setQueuedCmdFinished(); mStat->rxSuccess++; yield(); - notify(mPayload[iv->id].txCmd); + notify(RealTimeRunData_Debug); //iv->type == INV_TYPE_4CH ? 0x36 : 0x09 ); } bool build(uint8_t id, bool *complete) { From 574f6aed99866a33418806eec10ffa41a9dd62d9 Mon Sep 17 00:00:00 2001 From: rejoe2 Date: Sat, 1 Apr 2023 21:06:48 +0200 Subject: [PATCH 06/10] MI - fix comletion for 1ch MI --- src/hm/miPayload.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hm/miPayload.h b/src/hm/miPayload.h index 17d26fe8..02d49c53 100644 --- a/src/hm/miPayload.h +++ b/src/hm/miPayload.h @@ -659,7 +659,7 @@ const byteAssign_t InfoAssignment[] = { if ( datachan < 3 ) { mPayload[iv->id].dataAB[datachan] = true; } - if ( !mPayload[iv->id].dataAB[CH0] && mPayload[iv->id].dataAB[CH2] && mPayload[iv->id].dataAB[CH2] ) { + if ( !mPayload[iv->id].dataAB[CH0] && mPayload[iv->id].dataAB[CH1] && mPayload[iv->id].dataAB[CH2] ) { mPayload[iv->id].dataAB[CH0] = true; } From 26ec95d61e72d882d088eed702a2867f90287abf Mon Sep 17 00:00:00 2001 From: rejoe2 Date: Sun, 2 Apr 2023 13:45:18 +0200 Subject: [PATCH 07/10] MI - fixes to MQTT; uses classic hmRadio.h --- src/hm/hmRadio.h | 90 ++++++++++++++++++++++++++---------------------- 1 file changed, 48 insertions(+), 42 deletions(-) diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h index c1152e32..99867982 100644 --- a/src/hm/hmRadio.h +++ b/src/hm/hmRadio.h @@ -101,20 +101,19 @@ class HmRadio { // change the byte order of the DTU serial number and append the required 0x01 at the end DTU_RADIO_ID = ((uint64_t)(((dtuSn >> 24) & 0xFF) | ((dtuSn >> 8) & 0xFF00) | ((dtuSn << 8) & 0xFF0000) | ((dtuSn << 24) & 0xFF000000)) << 8) | 0x01; - SPIClass* spi; #ifdef ESP32 #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 - spi = new SPIClass(FSPI); + mSpi = new SPIClass(FSPI); #else - spi = new SPIClass(VSPI); + mSpi = new SPIClass(VSPI); #endif - spi->begin(sclk, miso, mosi, cs); + mSpi->begin(sclk, miso, mosi, cs); #else //the old ESP82xx cannot freely place their SPI pins - spi = new SPIClass(); - spi->begin(); + mSpi = new SPIClass(); + mSpi->begin(); #endif - mNrf24.begin(spi, ce, cs); + mNrf24.begin(mSpi, ce, cs); mNrf24.setRetries(3, 15); // 3*250us + 250us and 15 loops -> 15ms mNrf24.setChannel(mRfChLst[mRxChIdx]); @@ -124,7 +123,7 @@ class HmRadio { mNrf24.enableDynamicPayloads(); mNrf24.setCRCLength(RF24_CRC_16); mNrf24.setAddressWidth(5); - mNrf24.openReadingPipe(1, reinterpret_cast(&DTU_RADIO_ID)); + mNrf24.openReadingPipe(1, DTU_RADIO_ID); // enable all receiving interrupts mNrf24.maskIRQ(false, false, false); @@ -148,36 +147,32 @@ class HmRadio { bool tx_ok, tx_fail, rx_ready; mNrf24.whatHappened(tx_ok, tx_fail, rx_ready); // resets the IRQ pin to HIGH mNrf24.flush_tx(); // empty TX FIFO + //DBGPRINTLN("TX whatHappened Ch" + String(mRfChLst[mTxChIdx]) + " " + String(tx_ok) + String(tx_fail) + String(rx_ready)); - // start listening + // start listening on the default RX channel + mRxChIdx = 0; mNrf24.setChannel(mRfChLst[mRxChIdx]); mNrf24.startListening(); - uint32_t startMicros = micros(); - uint32_t loopMillis = millis(); - - uint32_t timeslot = 4088;//5110; //3066; //6132;//4088; - uint64_t tsCnt = 0; - while (millis()-loopMillis < 200) { - while (micros()-startMicros < timeslot) { // listen timeslot us to each channel + //uint32_t debug_ms = millis(); + uint16_t cnt = 300; // that is 60 times 5 channels + while (0 < cnt--) { + uint32_t startMillis = millis(); + while (millis()-startMillis < 4) { // listen 4ms to each channel if (mIrqRcvd) { mIrqRcvd = false; - DBGPRINTLN("*** time: " + String(tsCnt*(uint64_t)timeslot + (uint64_t)(micros()-startMicros)) + " ***"); if (getReceived()) { // everything received + //DBGPRINTLN("RX finished Cnt: " + String(300-cnt) + " time used: " + String(millis()-debug_ms)+ " ms"); return true; } } yield(); } - // switch to next RX channel - startMicros = micros(); - if(++mRxChIdx >= RF_CHANNELS) - mRxChIdx = 0; - mNrf24.setChannel(mRfChLst[mRxChIdx]); - tsCnt++; + switchRxCh(); // switch to next RX channel yield(); } // not finished but time is over + //DBGPRINTLN("RX not finished: 300 time used: " + String(millis()-debug_ms)+ " ms"); return true; } @@ -233,7 +228,8 @@ class HmRadio { } 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. - DPRINTLN(DBG_DEBUG, F("prepareDevInformCmd 0x") + String(cmd, HEX)); + DPRINT(DBG_DEBUG, F("prepareDevInformCmd 0x")); + DPRINTLN(DBG_DEBUG, String(cmd, HEX)); initPacket(invId, reqfld, ALL_FRAMES); mTxBuf[10] = cmd; // cid mTxBuf[11] = 0x00; @@ -245,9 +241,9 @@ class HmRadio { sendPacket(invId, 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 mid, uint8_t pid, bool isRetransmit, bool isMI=false) { initPacket(invId, mid, pid); - sendPacket(invId, 10, isRetransmit, appendCrc16); + sendPacket(invId, 10, isRetransmit, isMI); } void dumpBuf(uint8_t buf[], uint8_t len) { @@ -280,6 +276,7 @@ class HmRadio { bool getReceived(void) { bool tx_ok, tx_fail, rx_ready; mNrf24.whatHappened(tx_ok, tx_fail, rx_ready); // resets the IRQ pin to HIGH + //DBGPRINTLN("RX whatHappened Ch" + String(mRfChLst[mRxChIdx]) + " " + String(tx_ok) + String(tx_fail) + String(rx_ready)); bool isLastPackage = false; while(mNrf24.available()) { @@ -290,21 +287,29 @@ class HmRadio { p.ch = mRfChLst[mRxChIdx]; p.len = len; mNrf24.read(p.packet, len); - if (p.packet[0] != 0x00) { - mBufCtrl.push(p); - if (p.packet[0] == (TX_REQ_INFO + ALL_FRAMES)) // response from get information command - isLastPackage = (p.packet[9] > ALL_FRAMES); // > ALL_FRAMES indicates last packet received - else if (p.packet[0] == ( 0x0f + ALL_FRAMES) ) // response from MI get information command - isLastPackage = (p.packet[9] > 0x10); // > 0x10 indicates last packet received - else if ((p.packet[0] != 0x88) && (p.packet[0] != 0x92)) // ignore fragment number zero and MI status messages //#0 was p.packet[0] != 0x00 && - isLastPackage = true; // response from dev control command - } + mBufCtrl.push(p); + if (p.packet[0] == (TX_REQ_INFO + ALL_FRAMES)) // response from get information command + isLastPackage = (p.packet[9] > 0x81); // > 0x81 indicates last packet received + else if (p.packet[0] == ( 0x0f + ALL_FRAMES) ) // response from MI get information command + isLastPackage = (p.packet[9] > 0x11); // > 0x11 indicates last packet received + else if (p.packet[0] != 0x00 && p.packet[0] != 0x88 && p.packet[0] != 0x92) + // ignore fragment number zero and MI status messages + isLastPackage = true; // response from dev control command + yield(); } - yield(); } return isLastPackage; } + void switchRxCh() { + mNrf24.stopListening(); + // get next channel index + if(++mRxChIdx >= RF_CHANNELS) + mRxChIdx = 0; + mNrf24.setChannel(mRfChLst[mRxChIdx]); + mNrf24.startListening(); + } + void initPacket(uint64_t invId, uint8_t mid, uint8_t pid) { DPRINTLN(DBG_VERBOSE, F("initPacket, mid: ") + String(mid, HEX) + F(" pid: ") + String(pid, HEX)); memset(mTxBuf, 0, MAX_RF_PAYLOAD_SIZE); @@ -314,12 +319,12 @@ 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 len, bool isRetransmit, bool appendCrc16=false) { //DPRINTLN(DBG_VERBOSE, F("hmRadio.h:sendPacket")); //DPRINTLN(DBG_VERBOSE, "sent packet: #" + String(mSendCnt)); // append crc's - if (appendCrc16 && (len > 10)) { + if (appendCrc16 && len > 10) { // crc control data uint16_t crc = ah::crc16(&mTxBuf[10], len - 10); mTxBuf[len++] = (crc >> 8) & 0xff; @@ -329,10 +334,6 @@ class HmRadio { mTxBuf[len] = ah::crc8(mTxBuf, len); len++; - // set TX and RX channels - mTxChIdx = (mTxChIdx + 1) % RF_CHANNELS; - mRxChIdx = (mTxChIdx + 2) % RF_CHANNELS; - if(mSerialDebug) { DPRINT(DBG_INFO, F("TX ")); DBGPRINT(String(len)); @@ -347,6 +348,10 @@ class HmRadio { mNrf24.openWritingPipe(reinterpret_cast(&invId)); mNrf24.startWrite(mTxBuf, len, false); // false = request ACK response + // switch TX channel for next packet + if(++mTxChIdx >= RF_CHANNELS) + mTxChIdx = 0; + if(isRetransmit) mRetransmits++; else @@ -360,6 +365,7 @@ class HmRadio { uint8_t mTxChIdx; uint8_t mRxChIdx; + SPIClass* mSpi; RF24 mNrf24; uint8_t mTxBuf[MAX_RF_PAYLOAD_SIZE]; }; From 1e6a06b5805a3f398b2e2d78f480f0ba3a5e0f4e Mon Sep 17 00:00:00 2001 From: rejoe2 Date: Sun, 2 Apr 2023 19:23:57 +0200 Subject: [PATCH 08/10] hmRadio.h - change rx/tx channel hopping logic (#7) * hmRadio.h - change rx/tx channel hopping logic - patch originally provided by beegee3 - timings look very good for 3rd gen., and ok for MI in my environment over several restarts - runs stable on ESP32 - not sure wheather this also has any (negative or positive) impact to reboot problem with ESP8266 --- src/hm/hmRadio.h | 88 ++++++++++++++++++++-------------------------- src/hm/miPayload.h | 10 +++--- 2 files changed, 45 insertions(+), 53 deletions(-) diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h index 99867982..98fbb299 100644 --- a/src/hm/hmRadio.h +++ b/src/hm/hmRadio.h @@ -101,19 +101,20 @@ class HmRadio { // change the byte order of the DTU serial number and append the required 0x01 at the end DTU_RADIO_ID = ((uint64_t)(((dtuSn >> 24) & 0xFF) | ((dtuSn >> 8) & 0xFF00) | ((dtuSn << 8) & 0xFF0000) | ((dtuSn << 24) & 0xFF000000)) << 8) | 0x01; + SPIClass* spi; #ifdef ESP32 #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 - mSpi = new SPIClass(FSPI); + spi = new SPIClass(FSPI); #else - mSpi = new SPIClass(VSPI); + spi = new SPIClass(VSPI); #endif - mSpi->begin(sclk, miso, mosi, cs); + spi->begin(sclk, miso, mosi, cs); #else //the old ESP82xx cannot freely place their SPI pins - mSpi = new SPIClass(); - mSpi->begin(); + spi = new SPIClass(); + spi->begin(); #endif - mNrf24.begin(mSpi, ce, cs); + mNrf24.begin(spi, ce, cs); mNrf24.setRetries(3, 15); // 3*250us + 250us and 15 loops -> 15ms mNrf24.setChannel(mRfChLst[mRxChIdx]); @@ -123,7 +124,7 @@ class HmRadio { mNrf24.enableDynamicPayloads(); mNrf24.setCRCLength(RF24_CRC_16); mNrf24.setAddressWidth(5); - mNrf24.openReadingPipe(1, DTU_RADIO_ID); + mNrf24.openReadingPipe(1, reinterpret_cast(&DTU_RADIO_ID)); // enable all receiving interrupts mNrf24.maskIRQ(false, false, false); @@ -147,32 +148,32 @@ class HmRadio { bool tx_ok, tx_fail, rx_ready; mNrf24.whatHappened(tx_ok, tx_fail, rx_ready); // resets the IRQ pin to HIGH mNrf24.flush_tx(); // empty TX FIFO - //DBGPRINTLN("TX whatHappened Ch" + String(mRfChLst[mTxChIdx]) + " " + String(tx_ok) + String(tx_fail) + String(rx_ready)); - // start listening on the default RX channel - mRxChIdx = 0; + // start listening mNrf24.setChannel(mRfChLst[mRxChIdx]); mNrf24.startListening(); - //uint32_t debug_ms = millis(); - uint16_t cnt = 300; // that is 60 times 5 channels - while (0 < cnt--) { - uint32_t startMillis = millis(); - while (millis()-startMillis < 4) { // listen 4ms to each channel + uint32_t startMicros = micros(); + uint32_t loopMillis = millis(); + while (millis()-loopMillis < 400) { + while (micros()-startMicros < 5110) { // listen (4088us or?) 5110us to each channel if (mIrqRcvd) { mIrqRcvd = false; if (getReceived()) { // everything received - //DBGPRINTLN("RX finished Cnt: " + String(300-cnt) + " time used: " + String(millis()-debug_ms)+ " ms"); return true; } } - yield(); + //yield(); } - switchRxCh(); // switch to next RX channel - yield(); + // switch to next RX channel + startMicros = micros(); + if(++mRxChIdx >= RF_CHANNELS) + mRxChIdx = 0; + mNrf24.setChannel(mRfChLst[mRxChIdx]); + //yield(); } + yield(); // not finished but time is over - //DBGPRINTLN("RX not finished: 300 time used: " + String(millis()-debug_ms)+ " ms"); return true; } @@ -205,7 +206,6 @@ class HmRadio { } else { //MI 2nd gen. specific switch (cmd) { case TurnOn: - //mTxBuf[0] = 0x50; mTxBuf[9] = 0x55; mTxBuf[10] = 0xaa; break; @@ -241,9 +241,9 @@ class HmRadio { sendPacket(invId, 24, isRetransmit, true); } - void sendCmdPacket(uint64_t invId, uint8_t mid, uint8_t pid, bool isRetransmit, bool isMI=false) { + void sendCmdPacket(uint64_t invId, uint8_t mid, uint8_t pid, bool isRetransmit, bool appendCrc16=true) { initPacket(invId, mid, pid); - sendPacket(invId, 10, isRetransmit, isMI); + sendPacket(invId, 10, isRetransmit, appendCrc16); } void dumpBuf(uint8_t buf[], uint8_t len) { @@ -276,7 +276,6 @@ class HmRadio { bool getReceived(void) { bool tx_ok, tx_fail, rx_ready; mNrf24.whatHappened(tx_ok, tx_fail, rx_ready); // resets the IRQ pin to HIGH - //DBGPRINTLN("RX whatHappened Ch" + String(mRfChLst[mRxChIdx]) + " " + String(tx_ok) + String(tx_fail) + String(rx_ready)); bool isLastPackage = false; while(mNrf24.available()) { @@ -287,29 +286,21 @@ class HmRadio { p.ch = mRfChLst[mRxChIdx]; p.len = len; mNrf24.read(p.packet, len); - mBufCtrl.push(p); - if (p.packet[0] == (TX_REQ_INFO + ALL_FRAMES)) // response from get information command - isLastPackage = (p.packet[9] > 0x81); // > 0x81 indicates last packet received - else if (p.packet[0] == ( 0x0f + ALL_FRAMES) ) // response from MI get information command - isLastPackage = (p.packet[9] > 0x11); // > 0x11 indicates last packet received - else if (p.packet[0] != 0x00 && p.packet[0] != 0x88 && p.packet[0] != 0x92) - // ignore fragment number zero and MI status messages - isLastPackage = true; // response from dev control command - yield(); + if (p.packet[0] != 0x00) { + mBufCtrl.push(p); + if (p.packet[0] == (TX_REQ_INFO + ALL_FRAMES)) // response from get information command + isLastPackage = (p.packet[9] > ALL_FRAMES); // > ALL_FRAMES indicates last packet received + else if (p.packet[0] == ( 0x0f + ALL_FRAMES) ) // response from MI get information command + isLastPackage = (p.packet[9] > 0x10); // > 0x10 indicates last packet received + else if ((p.packet[0] != 0x88) && (p.packet[0] != 0x92)) // ignore fragment number zero and MI status messages //#0 was p.packet[0] != 0x00 && + isLastPackage = true; // response from dev control command + } } + yield(); } return isLastPackage; } - void switchRxCh() { - mNrf24.stopListening(); - // get next channel index - if(++mRxChIdx >= RF_CHANNELS) - mRxChIdx = 0; - mNrf24.setChannel(mRfChLst[mRxChIdx]); - mNrf24.startListening(); - } - void initPacket(uint64_t invId, uint8_t mid, uint8_t pid) { DPRINTLN(DBG_VERBOSE, F("initPacket, mid: ") + String(mid, HEX) + F(" pid: ") + String(pid, HEX)); memset(mTxBuf, 0, MAX_RF_PAYLOAD_SIZE); @@ -319,12 +310,12 @@ class HmRadio { mTxBuf[9] = pid; } - void sendPacket(uint64_t invId, uint8_t len, bool isRetransmit, bool appendCrc16=false) { + void sendPacket(uint64_t invId, uint8_t len, bool isRetransmit, bool appendCrc16=true) { //DPRINTLN(DBG_VERBOSE, F("hmRadio.h:sendPacket")); //DPRINTLN(DBG_VERBOSE, "sent packet: #" + String(mSendCnt)); // append crc's - if (appendCrc16 && len > 10) { + if (appendCrc16 && (len > 10)) { // crc control data uint16_t crc = ah::crc16(&mTxBuf[10], len - 10); mTxBuf[len++] = (crc >> 8) & 0xff; @@ -334,6 +325,10 @@ class HmRadio { mTxBuf[len] = ah::crc8(mTxBuf, len); len++; + // set TX and RX channels + mTxChIdx = (mTxChIdx + 1) % RF_CHANNELS; + mRxChIdx = (mTxChIdx + 2) % RF_CHANNELS; + if(mSerialDebug) { DPRINT(DBG_INFO, F("TX ")); DBGPRINT(String(len)); @@ -348,10 +343,6 @@ class HmRadio { mNrf24.openWritingPipe(reinterpret_cast(&invId)); mNrf24.startWrite(mTxBuf, len, false); // false = request ACK response - // switch TX channel for next packet - if(++mTxChIdx >= RF_CHANNELS) - mTxChIdx = 0; - if(isRetransmit) mRetransmits++; else @@ -365,7 +356,6 @@ class HmRadio { uint8_t mTxChIdx; uint8_t mRxChIdx; - SPIClass* mSpi; RF24 mNrf24; uint8_t mTxBuf[MAX_RF_PAYLOAD_SIZE]; }; diff --git a/src/hm/miPayload.h b/src/hm/miPayload.h index 02d49c53..6d2a5d1a 100644 --- a/src/hm/miPayload.h +++ b/src/hm/miPayload.h @@ -151,7 +151,8 @@ class MiPayload { cmd2 = cmd == SystemConfigPara ? 0x01 : 0x00; //perhaps we can only try to get second frame? mSys->Radio.sendCmdPacket(iv->radioId.u64, cmd, cmd2, false, false); } 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); }; mPayload[iv->id].txCmd = cmd; @@ -479,8 +480,8 @@ const byteAssign_t InfoAssignment[] = { } DBGPRINT(F(" 0x")); DBGHEXLN(cmd); - //mSys->Radio.sendCmdPacket(iv->radioId.u64, cmd, cmd, true); - mSys->Radio.prepareDevInformCmd(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex, true, cmd); + mSys->Radio.sendCmdPacket(iv->radioId.u64, cmd, cmd, true, false); + //mSys->Radio.prepareDevInformCmd(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex, true, cmd); yield(); } } @@ -496,7 +497,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.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); } } /*else { // payload complete From 1e81a3e9634c3c51257d7f6872ed446ad776f340 Mon Sep 17 00:00:00 2001 From: rejoe2 Date: Tue, 4 Apr 2023 15:27:03 +0200 Subject: [PATCH 09/10] faster request after power limit and more yield() calls in while() loops (thx to beegee3) --- src/hm/hmPayload.h | 2 ++ src/hm/hmRadio.h | 34 ++++++++++++++++++++++------------ 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/hm/hmPayload.h b/src/hm/hmPayload.h index de99d41b..e08dd909 100644 --- a/src/hm/hmPayload.h +++ b/src/hm/hmPayload.h @@ -210,6 +210,8 @@ class HmPayload { iv->clearCmdQueue(); iv->enqueCommand(SystemConfigPara); // read back power limit + if(mHighPrioIv == NULL) // do it immediately if possible + mHighPrioIv = iv; } iv->devControlCmd = Init; } diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h index 98fbb299..b848d377 100644 --- a/src/hm/hmRadio.h +++ b/src/hm/hmRadio.h @@ -52,12 +52,15 @@ template = RF_CHANNELS) mRxChIdx = 0; mNrf24.setChannel(mRfChLst[mRxChIdx]); - //yield(); + yield(); } - yield(); // not finished but time is over return true; } @@ -206,6 +208,7 @@ class HmRadio { } else { //MI 2nd gen. specific switch (cmd) { case TurnOn: + //mTxBuf[0] = 0x50; mTxBuf[9] = 0x55; mTxBuf[10] = 0xaa; break; @@ -228,8 +231,10 @@ class HmRadio { } 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. - DPRINT(DBG_DEBUG, F("prepareDevInformCmd 0x")); - DPRINTLN(DBG_DEBUG, String(cmd, HEX)); + if(mSerialDebug) { + DPRINT(DBG_DEBUG, F("prepareDevInformCmd 0x")); + DPRINTLN(DBG_DEBUG,String(cmd, HEX)); + } initPacket(invId, reqfld, ALL_FRAMES); mTxBuf[10] = cmd; // cid mTxBuf[11] = 0x00; @@ -302,7 +307,12 @@ class HmRadio { } void initPacket(uint64_t invId, uint8_t mid, uint8_t pid) { - DPRINTLN(DBG_VERBOSE, F("initPacket, mid: ") + String(mid, HEX) + F(" pid: ") + String(pid, HEX)); + if(mSerialDebug) { + DPRINT(DBG_VERBOSE, F("initPacket, mid: ")); + DPRINT(DBG_VERBOSE, String(mid, HEX)); + DPRINT(DBG_VERBOSE,F(" pid: ")); + DPRINTLN(DBG_VERBOSE,String(pid, HEX)); + } memset(mTxBuf, 0, MAX_RF_PAYLOAD_SIZE); mTxBuf[0] = mid; // message id CP_U32_BigEndian(&mTxBuf[1], (invId >> 8)); From 8d8cab60993e970426084578b79564429e421f6a Mon Sep 17 00:00:00 2001 From: lumapu Date: Tue, 4 Apr 2023 23:34:16 +0200 Subject: [PATCH 10/10] minor corrections --- src/hm/hmPayload.h | 3 +-- src/hm/hmRadio.h | 32 ++++++++++++++++---------------- src/hm/miPayload.h | 3 +-- 3 files changed, 18 insertions(+), 20 deletions(-) diff --git a/src/hm/hmPayload.h b/src/hm/hmPayload.h index e08dd909..b04ee8f3 100644 --- a/src/hm/hmPayload.h +++ b/src/hm/hmPayload.h @@ -116,8 +116,7 @@ class HmPayload { mStat->rxFailNoAnser++; // got nothing if (mSerialDebug) DBGPRINTLN(F("enqueued cmd failed/timeout")); - } - else { + } else { mStat->rxFail++; // got fragments but not complete response if (mSerialDebug) { DBGPRINT(F("no complete Payload received! (retransmits: ")); diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h index b848d377..35993829 100644 --- a/src/hm/hmRadio.h +++ b/src/hm/hmRadio.h @@ -54,12 +54,12 @@ class HmRadio { HmRadio() : mNrf24(CE_PIN, CS_PIN, SPI_SPEED) { if(mSerialDebug) { DPRINT(DBG_VERBOSE, F("hmRadio.h : HmRadio():mNrf24(CE_PIN: ")); - DPRINT(DBG_VERBOSE, String(CE_PIN)); - DPRINT(DBG_VERBOSE, F(", CS_PIN: ")); - DPRINT(DBG_VERBOSE, String(CS_PIN)); - DPRINT(DBG_VERBOSE, F(", SPI_SPEED: ")); - DPRINT(DBG_VERBOSE, String(SPI_SPEED)); - DPRINTLN(DBG_VERBOSE, F(")")); + DBGPRINT(String(CE_PIN)); + DBGPRINT(F(", CS_PIN: ")); + DBGPRINT(String(CS_PIN)); + DBGPRINT(F(", SPI_SPEED: ")); + DBGPRINT(String(SPI_SPEED)); + DBGPRINTLN(F(")")); } // Depending on the program, the module can work on 2403, 2423, 2440, 2461 or 2475MHz. @@ -104,20 +104,19 @@ class HmRadio { // change the byte order of the DTU serial number and append the required 0x01 at the end DTU_RADIO_ID = ((uint64_t)(((dtuSn >> 24) & 0xFF) | ((dtuSn >> 8) & 0xFF00) | ((dtuSn << 8) & 0xFF0000) | ((dtuSn << 24) & 0xFF000000)) << 8) | 0x01; - SPIClass* spi; #ifdef ESP32 #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 - spi = new SPIClass(FSPI); + mSpi = new SPIClass(FSPI); #else - spi = new SPIClass(VSPI); + mSpi = new SPIClass(VSPI); #endif - spi->begin(sclk, miso, mosi, cs); + mSpi->begin(sclk, miso, mosi, cs); #else //the old ESP82xx cannot freely place their SPI pins - spi = new SPIClass(); - spi->begin(); + mSpi = new SPIClass(); + mSpi->begin(); #endif - mNrf24.begin(spi, ce, cs); + mNrf24.begin(mSpi, ce, cs); mNrf24.setRetries(3, 15); // 3*250us + 250us and 15 loops -> 15ms mNrf24.setChannel(mRfChLst[mRxChIdx]); @@ -309,9 +308,9 @@ class HmRadio { void initPacket(uint64_t invId, uint8_t mid, uint8_t pid) { if(mSerialDebug) { DPRINT(DBG_VERBOSE, F("initPacket, mid: ")); - DPRINT(DBG_VERBOSE, String(mid, HEX)); - DPRINT(DBG_VERBOSE,F(" pid: ")); - DPRINTLN(DBG_VERBOSE,String(pid, HEX)); + DHEX(mid); + DBGPRINT(F(" pid: ")); + DBGHEXLN(pid); } memset(mTxBuf, 0, MAX_RF_PAYLOAD_SIZE); mTxBuf[0] = mid; // message id @@ -366,6 +365,7 @@ class HmRadio { uint8_t mTxChIdx; uint8_t mRxChIdx; + SPIClass* mSpi; RF24 mNrf24; uint8_t mTxBuf[MAX_RF_PAYLOAD_SIZE]; }; diff --git a/src/hm/miPayload.h b/src/hm/miPayload.h index 6d2a5d1a..fd922c8b 100644 --- a/src/hm/miPayload.h +++ b/src/hm/miPayload.h @@ -92,8 +92,7 @@ class MiPayload { mStat->rxFailNoAnser++; // got nothing if (mSerialDebug) DBGPRINTLN(F("enqueued cmd failed/timeout")); - } - else { + } else { mStat->rxFail++; // got "fragments" (part of the required messages) // but no complete set of responses if (mSerialDebug) {