Browse Source

Merge branch 'development03' of https://github.com/rejoe2/ahoy into rejoe2-development03

pull/1239/head
lumapu 11 months ago
parent
commit
904c34b4e3
  1. 4
      src/hm/CommQueue.h
  2. 150
      src/hm/Communication.h
  3. 6
      src/hm/Heuristic.h
  4. 7
      src/hm/hmInverter.h
  5. 23
      src/hm/hmRadio.h
  6. 4
      src/hm/radio.h
  7. 7
      src/utils/helper.cpp
  8. 2
      src/utils/helper.h

4
src/hm/CommQueue.h

@ -85,6 +85,10 @@ class CommQueue {
mQueue[mRdPtr].attempts--;
}
void incrAttempt(void) {
mQueue[mRdPtr].attempts++;
}
void inc(uint8_t *ptr) {
if(++(*ptr) >= N)
*ptr = 0;

150
src/hm/Communication.h

@ -11,9 +11,10 @@
#include "../utils/crc.h"
#include "Heuristic.h"
#define MI_TIMEOUT 250
#define DEFAULT_TIMEOUT 500
#define SINGLEFR_TIMEOUT 60
#define MI_TIMEOUT 250 // timeout for MI type requests
#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 MAX_BUFFER 250
typedef std::function<void(uint8_t, Inverter<> *)> payloadListenerType;
@ -43,7 +44,8 @@ class Communication : public CommQueue<> {
if(!valid)
return; // empty
uint16_t timeout = q->iv->ivGen != IV_MI ? DEFAULT_TIMEOUT : MI_TIMEOUT;
uint16_t timeout = q->iv->ivGen != IV_MI ? (q->iv->mGotFragment && q->iv->mGotLastMsg) ? SINGLEFR_TIMEOUT : DEFAULT_TIMEOUT : MI_TIMEOUT;
uint16_t timeout_min = q->iv->ivGen != IV_MI ? q->iv->mGotFragment ? SINGLEFR_TIMEOUT : FRSTMSG_TIMEOUT : MI_TIMEOUT;
bool testMode = false;
switch(mState) {
@ -55,11 +57,13 @@ class Communication : public CommQueue<> {
mLocalBuf[i].len = 0;
}
mHeu.printStatus(q->iv);
if(q->iv->radio->isSerialDebug())
mHeu.printStatus(q->iv);
mHeu.getTxCh(q->iv);
testMode = mHeu.getTestModeEnabled();
mGotFragment = false;
mFirstTry = mFirstTry ? false : ( (IV_HM == q->iv->ivGen) || (IV_MI == q->iv->ivGen) ) && (q->iv->isAvailable()); //) || (millis() < 120000));}
q->iv->mGotFragment = false;
q->iv->mGotLastMsg = false;
mFirstTry = mFirstTry ? false : ( ( (IV_HM == q->iv->ivGen) || (IV_MI == q->iv->ivGen) ) && (q->iv->isAvailable()) || (millis() < 120000) );
if(NULL == q->iv->radio)
cmdDone(true); // can't communicate while radio is not defined!
mState = States::START;
@ -83,12 +87,30 @@ class Communication : public CommQueue<> {
q->iv->radio->prepareDevInformCmd(q->iv, q->cmd, q->ts, q->iv->alarmLastId, false);
if(!testMode)
q->iv->radioStatistics.txCnt++;
mWaitTimeout = millis() + timeout;
mWaitTimeout = millis() + timeout;
mWaitTimeout_min = millis() + timeout_min;
setAttempt();
mState = States::WAIT;
break;
case States::WAIT:
if(millis() > mWaitTimeout_min) {
if(!q->iv->mGotFragment) { // nothing received yet?
if(q->iv->mGotLastMsg) {
//mState = States::CHECK_FRAMES;
mWaitTimeout = mWaitTimeout_min;
}
} else if(mFirstTry) {
DPRINT_IVID(DBG_INFO, q->iv->id);
DBGPRINTLN(F("second try"));
mFirstTry = false;
if(!testMode)
q->iv->radioStatistics.retransmits++; // got nothing
mState = States::START;
break;
}
}
if(millis() < mWaitTimeout)
return;
mState = States::CHECK_FRAMES;
@ -102,7 +124,7 @@ class Communication : public CommQueue<> {
DBGPRINT(String(millis() - mWaitTimeout + timeout));
DBGPRINTLN(F("ms"));
if(!mGotFragment && !mFirstTry) {
if(!q->iv->mGotFragment) {
if(!testMode)
q->iv->radioStatistics.rxFailNoAnser++; // got nothing
mHeu.setGotNothing(q->iv);
@ -118,7 +140,6 @@ class Communication : public CommQueue<> {
break;
}
mGotFragment = true;
mFirstTry = false; // for correct reset
States nextState = States::RESET;
while(!q->iv->radio->mBufCtrl.empty()) {
@ -140,7 +161,7 @@ class Communication : public CommQueue<> {
DBGPRINT(F(", "));
DBGPRINT(String(p->rssi));
DBGPRINT(F("dBm | "));
ah::dumpBuf(p->packet, p->len);
ah::dumpBuf(p->packet, p->len, 1, 8, "#"+String(q->iv->id));
if(checkIvSerial(&p->packet[1], q->iv)) {
if(!testMode)
@ -178,39 +199,38 @@ class Communication : public CommQueue<> {
break;
case States::CHECK_PACKAGE:
uint8_t framnr = 0;
if(0 == mMaxFrameId) {
setAttempt();
DPRINT_IVID(DBG_WARN, q->iv->id);
DBGPRINT(F("frame missing: request retransmit ("));
DBGPRINT(String(q->attempts));
DBGPRINTLN(F(" attempts left)"));
uint8_t i = 0;
while(i < MAX_PAYLOAD_ENTRIES) {
if(mLocalBuf[i].len == 0)
if(mLocalBuf[i].len == 0) {
framnr = i+1;
break;
}
i++;
}
sendRetransmit(q, i);
return;
}
for(uint8_t i = 0; i < mMaxFrameId; i++) {
if(mLocalBuf[i].len == 0) {
setAttempt();
if(!framnr) {
for(uint8_t i = 0; i < mMaxFrameId; i++) {
if(mLocalBuf[i].len == 0) {
framnr = i+1;
break;
}
}
}
DPRINT_IVID(DBG_WARN, q->iv->id);
DBGPRINT(F("frame "));
DBGPRINT(String(i + 1));
DBGPRINT(F(" missing: request retransmit ("));
DBGPRINT(String(q->attempts));
DBGPRINTLN(F(" attempts left)"));
if(framnr) {
setAttempt();
sendRetransmit(q, i);
return;
}
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);
return;
}
mHeu.setGotAll(q->iv);
@ -413,9 +433,6 @@ class Communication : public CommQueue<> {
inline void miHwDecode(packet_t *p, const queue_s *q) {
record_t<> *rec = q->iv->getRecordStruct(InverterDevInform_All); // choose the record structure
rec->ts = q->ts;
//mPayload[iv->id].gotFragment = true;
uint8_t multi_parts = 0;
/*
Polling the device software and hardware version number command
start byte Command word routing address target address User data check end byte
@ -458,14 +475,13 @@ class Communication : public CommQueue<> {
q->iv->isConnected = true;
//if(mSerialDebug) {
DPRINT_IVID(DBG_INFO, q->iv->id);
DPRINT(DBG_INFO,F("HW_VER is "));
DBGPRINT(F("HW_VER is "));
DBGPRINTLN(String((p->packet[24] << 8) + p->packet[25]));
//}
record_t<> *rec = q->iv->getRecordStruct(InverterDevInform_Simple); // choose the record structure
rec->ts = q->ts;
q->iv->setValue(1, rec, (uint32_t) ((p->packet[24] << 8) + p->packet[25])/1);
//mPayload[iv->id].multi_parts +=4;
multi_parts +=4;
q->iv->miMultiParts +=4;
} else if ( p->packet[9] == 0x01 || p->packet[9] == 0x10 ) {//second frame for MI, 3rd gen. answers in 0x10
DPRINT_IVID(DBG_INFO, q->iv->id);
if ( p->packet[9] == 0x01 ) {
@ -486,19 +502,19 @@ class Communication : public CommQueue<> {
//if(mSerialDebug) {
DPRINT(DBG_INFO,F("HW_FB_TLmValue "));
DBGPRINTLN(String((p->packet[14] << 8) + p->packet[15]));
DPRINT(DBG_INFO,F("HW_FB_ReSPRT "));
DBGPRINT(F("HW_FB_ReSPRT "));
DBGPRINTLN(String((p->packet[16] << 8) + p->packet[17]));
DPRINT(DBG_INFO,F("HW_GridSamp_ResValule "));
DBGPRINT(F("HW_GridSamp_ResValule "));
DBGPRINTLN(String((p->packet[18] << 8) + p->packet[19]));
DPRINT(DBG_INFO,F("HW_ECapValue "));
DBGPRINT(F("HW_ECapValue "));
DBGPRINTLN(String((p->packet[20] << 8) + p->packet[21]));
DPRINT(DBG_INFO,F("Matching_APPFW_PN "));
DBGPRINT(F("Matching_APPFW_PN "));
DBGPRINTLN(String((uint32_t) (((p->packet[22] << 8) | p->packet[23]) << 8 | p->packet[24]) << 8 | p->packet[25]));
//}
//notify(InverterDevInform_Simple, iv);
//mPayload[iv->id].multi_parts +=2;
multi_parts +=2;
//notify(InverterDevInform_All, iv);
if(NULL != mCbPayload)
(mCbPayload)(InverterDevInform_All, q->iv);
q->iv->miMultiParts +=2;
} else {
DBGPRINTLN(F("3rd gen. inverter!"));
}
@ -515,21 +531,24 @@ class Communication : public CommQueue<> {
//if(mSerialDebug) {
DPRINT(DBG_INFO,F("APPFW_MINVER "));
DBGPRINTLN(String((p->packet[10] << 8) + p->packet[11]));
DPRINT(DBG_INFO,F("HWInfoAddr "));
DBGPRINT(F("HWInfoAddr "));
DBGPRINTLN(String((p->packet[12] << 8) + p->packet[13]));
DPRINT(DBG_INFO,F("PNInfoCRC_gusv "));
DBGPRINT(F("PNInfoCRC_gusv "));
DBGPRINTLN(String((p->packet[14] << 8) + p->packet[15]));
//}
//mPayload[iv->id].multi_parts++;
multi_parts++;
if(NULL != mCbPayload)
(mCbPayload)(InverterDevInform_Simple, q->iv);
q->iv->miMultiParts++;
}
if(multi_parts > 5) {
if(q->iv->miMultiParts > 5) {
cmdDone(true);
mState = States::RESET;
q->iv->radioStatistics.rxSuccess++;
mHeu.setGotAll(q->iv);
q->iv->miMultiParts = 0;
} else {
mHeu.setGotFragment(q->iv);
mState = States::WAIT;
}
/*if (mPayload[iv->id].multi_parts > 5) {
@ -568,9 +587,8 @@ class Communication : public CommQueue<> {
q->iv->setValue(q->iv->getPosByChFld(0, FLD_T, rec), rec, (float) ((int16_t)(p->packet[21] << 8) + p->packet[22])/10);
q->iv->setValue(q->iv->getPosByChFld(0, FLD_IRR, rec), rec, (float) (calcIrradiation(q->iv, datachan)));
//mPayload[q->iv->id].rssi[(datachan-1)] = p->rssi;
if (datachan == 1) //mPayload[q->iv->id].rssi[(datachan-1)] = p->rssi;
if (datachan == 1)
q->iv->rssi = p->rssi;
else if(q->iv->rssi > p->rssi)
q->iv->rssi = p->rssi;
@ -597,6 +615,7 @@ class Communication : public CommQueue<> {
} else if((p->packet[0] == (MI_REQ_CH1 + ALL_FRAMES)) && (q->iv->type == INV_TYPE_2CH)) {
//addImportant(q->iv, MI_REQ_CH2);
miNextRequest(MI_REQ_CH2, q);
//use also miMultiParts here for better statistics?
mHeu.setGotFragment(q->iv);
} else { // first data msg for 1ch, 2nd for 2ch
miComplete(q->iv);
@ -604,25 +623,24 @@ class Communication : public CommQueue<> {
}
inline void miNextRequest(uint8_t cmd, const queue_s *q) {
//setAttempt();
incrAttempt(); // if function is called, we got something, and we necessarily need more transmissions for MI types...
DPRINT_IVID(DBG_WARN, q->iv->id);
DBGPRINT(F("next request ("));
DBGPRINT(String(q->attempts));
DBGPRINT(F(" attempts left): 0x"));
DBGHEXLN(cmd);
if(q->attempts) {
//if(q->attempts) {
q->iv->radio->sendCmdPacket(q->iv, cmd, 0x00, true);
q->iv->radioStatistics.retransmits++;
mWaitTimeout = millis() + MI_TIMEOUT;
//chgCmd(Inverter<> *iv, uint8_t cmd, bool delOnPop = true)
chgCmd(cmd);
mState = States::WAIT;
} else {
/*} else {
add(q, true);
cmdDone();
mState = States::RESET;
}
}*/
}
inline void miStsConsolidate(const queue_s *q, uint8_t stschan, record_t<> *rec, uint8_t uState, uint8_t uEnum, uint8_t lState = 0, uint8_t lEnum = 0) {
@ -699,13 +717,10 @@ class Communication : public CommQueue<> {
inline 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;
//if (mSerialDebug) {
if (iv->radio->isSerialDebug()) {
DPRINT_IVID(DBG_INFO, iv->id);
DBGPRINTLN(F("got all data msgs"));
//}
}
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug);
iv->setValue(iv->getPosByChFld(0, FLD_YD, rec), rec, calcYieldDayCh0(iv,0));
@ -751,9 +766,10 @@ class Communication : public CommQueue<> {
private:
States mState = States::RESET;
uint32_t *mTimestamp;
uint32_t mWaitTimeout = 0;
uint32_t mWaitTimeout = 0;
uint32_t mWaitTimeout_min = 0;
std::array<frame_t, MAX_PAYLOAD_ENTRIES> mLocalBuf;
bool mGotFragment = false;
//bool mGotFragment = false;
bool mFirstTry = false;
uint8_t mMaxFrameId;
uint8_t mPayload[MAX_BUFFER];

6
src/hm/Heuristic.h

@ -62,7 +62,7 @@ class Heuristic {
void printStatus(Inverter<> *iv) {
DPRINT_IVID(DBG_INFO, iv->id);
DBGPRINT(F("CH qualities:"));
DBGPRINT(F("Radio infos:"));
for(uint8_t i = 0; i < RF_MAX_CHANNEL_ID; i++) {
DBGPRINT(F(" "));
DBGPRINT(String(iv->txRfQuality[i]));
@ -74,7 +74,9 @@ class Heuristic {
DBGPRINT(F(", f: "));
DBGPRINT(String(iv->radioStatistics.rxFail));
DBGPRINT(F(", n: "));
DBGPRINTLN(String(iv->radioStatistics.rxFailNoAnser));
DBGPRINT(String(iv->radioStatistics.rxFailNoAnser));
DBGPRINT(F(" | p: ")); // better debugging for helpers...
DBGPRINTLN(String(iv->config->powerLevel));
}
bool getTestModeEnabled(void) {

7
src/hm/hmInverter.h

@ -125,6 +125,10 @@ class Inverter {
uint16_t alarmCnt; // counts the total number of occurred alarms
uint16_t alarmLastId; // lastId which was received
int8_t rssi; // RSSI
uint8_t miMultiParts; // helper info for MI multiframe msgs
uint8_t outstandingFrames; // helper info to count difference between expected and received frames
bool mGotFragment; // shows if inverter has sent at least one fragment
bool mGotLastMsg; // shows if inverter has already finished transmission cycle
Radio *radio; // pointer to associated radio class
statistics_t radioStatistics; // information about transmitted, failed, ... packets
int8_t txRfQuality[5]; // heuristics tx quality (check 'Heuristics.h')
@ -150,8 +154,11 @@ class Inverter {
alarmCnt = 0;
alarmLastId = 0;
rssi = -127;
miMultiParts = 0;
mGotLastMsg = false;
radio = NULL;
commEnabled = true;
memset(&radioStatistics, 0, sizeof(statistics_t));
memset(txRfQuality, -6, 5);

23
src/hm/hmRadio.h

@ -252,17 +252,25 @@ class HmRadio : public Radio {
p.millis = millis() - mMillis;
mNrf24.read(p.packet, p.len);
if (p.packet[0] != 0x00) {
if(!checkIvSerial(&p.packet[1], mLastIv)) {
DPRINT(DBG_WARN, "RX other inverter: ");
ah::dumpBuf(p.packet, p.len);
return false;
}
mLastIv->mGotFragment = true;
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 &&
else if ((p.packet[0] != 0x88) && (p.packet[0] != 0x92)) // ignore MI status messages //#0 was p.packet[0] != 0x00 &&
isLastPackage = true; // response from dev control command
}
}
yield();
}
if(isLastPackage)
mLastIv->mGotLastMsg = true;
return isLastPackage;
}
@ -280,7 +288,7 @@ class HmRadio : public Radio {
DBGPRINT(" CH");
DBGPRINT(String(mTxChIdx));
DBGPRINT(F(" | "));
ah::dumpBuf(mTxBuf, len);
ah::dumpBuf(mTxBuf, len, 1, 4, "#"+String(iv->id));
}
mNrf24.stopListening();
@ -300,10 +308,21 @@ class HmRadio : public Radio {
return iv->ivGen;
}
inline bool checkIvSerial(uint8_t buf[], Inverter<> *iv) {
uint8_t tmp[4];
CP_U32_BigEndian(tmp, iv->radioId.u64 >> 8);
for(uint8_t i = 0; i < 4; i++) {
if(tmp[i] != buf[i])
return false;
}
return true;
}
uint64_t DTU_RADIO_ID;
uint8_t mRfChLst[RF_CHANNELS] = {03, 23, 40, 61, 75}; // channel List:2403, 2423, 2440, 2461, 2475MHz
uint8_t mTxChIdx = 0;
uint8_t mRxChIdx = 0;
bool mGotLastMsg = false;
uint32_t mMillis;
SPIClass* mSpi;

4
src/hm/radio.h

@ -38,6 +38,10 @@ class Radio {
mSerialDebug = true;
}
bool isSerialDebug() {
return mSerialDebug;
}
void sendCmdPacket(Inverter<> *iv, uint8_t mid, uint8_t pid, bool isRetransmit, bool appendCrc16=true) {
initPacket(getIvId(iv), mid, pid);
sendPacket(iv, 10, isRetransmit, appendCrc16);

7
src/utils/helper.cpp

@ -86,9 +86,12 @@ namespace ah {
return ret;
}
void dumpBuf(uint8_t buf[], uint8_t len) {
void dumpBuf(uint8_t buf[], uint8_t len, uint8_t firstRepl, uint8_t lastRepl, String repl) {
for(uint8_t i = 0; i < len; i++) {
DHEX(buf[i]);
if(i < firstRepl || i > lastRepl)
DHEX(buf[i]);
else
DBGPRINT(repl);
DBGPRINT(" ");
}
DBGPRINTLN("");

2
src/utils/helper.h

@ -45,7 +45,7 @@ namespace ah {
String getDateTimeStrFile(time_t t);
String getTimeStr(time_t t);
uint64_t Serial2u64(const char *val);
void dumpBuf(uint8_t buf[], uint8_t len);
void dumpBuf(uint8_t buf[], uint8_t len, uint8_t firstRepl = 0, uint8_t lastRepl = 0, String repl = "");
}
#endif /*__HELPER_H__*/

Loading…
Cancel
Save