Browse Source

0.8.1101

known issues:
* crashes from time to time?
* has MI commands in HM pipe?
pull/1239/head
lumapu 1 year ago
parent
commit
6d6686b44e
  1. 3
      src/CHANGES.md
  2. 2
      src/defines.h
  3. 112
      src/hm/Communication.h
  4. 5
      src/web/html/update.html

3
src/CHANGES.md

@ -1,5 +1,8 @@
# Development Changes # Development Changes
## 0.8.11 - 2023-11-19
* slightly improved communication, thx @rejoe2
## 0.8.10 - 2023-11-19 ## 0.8.10 - 2023-11-19
* fix Mi and HM inverter communication #1235 * fix Mi and HM inverter communication #1235
* added privacy mode option #1211 * added privacy mode option #1211

2
src/defines.h

@ -13,7 +13,7 @@
//------------------------------------- //-------------------------------------
#define VERSION_MAJOR 0 #define VERSION_MAJOR 0
#define VERSION_MINOR 8 #define VERSION_MINOR 8
#define VERSION_PATCH 10 #define VERSION_PATCH 1101
//------------------------------------- //-------------------------------------
typedef struct { typedef struct {

112
src/hm/Communication.h

@ -46,9 +46,8 @@ class Communication : public CommQueue<> {
if(!valid) if(!valid)
return; // empty return; // empty
uint16_t timeout = q->iv->ivGen != IV_MI ? ((q->iv->mGotFragment && q->iv->mGotLastMsg) ? SINGLEFR_TIMEOUT : DEFAULT_TIMEOUT) : MI_TIMEOUT; uint16_t timeout = (q->iv->ivGen = IV_MI) ? MI_TIMEOUT : ((q->iv->mGotFragment && q->iv->mGotLastMsg) ? SINGLEFR_TIMEOUT : DEFAULT_TIMEOUT);
uint16_t timeout_min = q->iv->ivGen != IV_MI ? ((q->iv->mGotFragment) ? SINGLEFR_TIMEOUT : FRSTMSG_TIMEOUT) : MI_TIMEOUT; uint16_t timeout_min = (q->iv->ivGen = IV_MI) ? MI_TIMEOUT : ((q->iv->mGotFragment) ? SINGLEFR_TIMEOUT : FRSTMSG_TIMEOUT);
bool testMode = false;
switch(mState) { switch(mState) {
case States::RESET: case States::RESET:
@ -62,10 +61,8 @@ class Communication : public CommQueue<> {
if(*mSerialDebug) if(*mSerialDebug)
mHeu.printStatus(q->iv); mHeu.printStatus(q->iv);
mHeu.getTxCh(q->iv); mHeu.getTxCh(q->iv);
testMode = mHeu.getTestModeEnabled();
q->iv->mGotFragment = false; q->iv->mGotFragment = false;
q->iv->mGotLastMsg = 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) if(NULL == q->iv->radio)
cmdDone(true); // can't communicate while radio is not defined! cmdDone(true); // can't communicate while radio is not defined!
mState = States::START; mState = States::START;
@ -87,7 +84,7 @@ class Communication : public CommQueue<> {
q->iv->radio->sendControlPacket(q->iv, q->cmd, q->iv->powerLimit, false); q->iv->radio->sendControlPacket(q->iv, q->cmd, q->iv->powerLimit, false);
} 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(!testMode) if(!mHeu.getTestModeEnabled())
q->iv->radioStatistics.txCnt++; q->iv->radioStatistics.txCnt++;
mWaitTimeout = millis() + timeout; mWaitTimeout = millis() + timeout;
mWaitTimeout_min = millis() + timeout_min; mWaitTimeout_min = millis() + timeout_min;
@ -97,16 +94,17 @@ class Communication : public CommQueue<> {
case States::WAIT: case States::WAIT:
if(millis() > mWaitTimeout_min) { if(millis() > mWaitTimeout_min) {
if(!q->iv->mGotFragment) { // nothing received yet? if(q->iv->mGotFragment) { // nothing received yet?
if(q->iv->mGotLastMsg) { if(q->iv->mGotLastMsg) {
//mState = States::CHECK_FRAMES; //mState = States::CHECK_FRAMES;
mWaitTimeout = mWaitTimeout_min; mWaitTimeout = mWaitTimeout_min;
} }
} else if(mFirstTry) { } else if(mFirstTry) {
DPRINT_IVID(DBG_INFO, q->iv->id); DPRINT_IVID(DBG_INFO, q->iv->id);
DBGPRINTLN(F("second try")); DBGPRINT(String(millis() - mWaitTimeout_min + timeout_min));
DBGPRINTLN(F("ms - second try"));
mFirstTry = false; mFirstTry = false;
if(!testMode) if(!mHeu.getTestModeEnabled())
q->iv->radioStatistics.retransmits++; // got nothing q->iv->radioStatistics.retransmits++; // got nothing
mState = States::START; mState = States::START;
break; break;
@ -119,7 +117,7 @@ class Communication : public CommQueue<> {
break; break;
case States::CHECK_FRAMES: { case States::CHECK_FRAMES: {
if(!q->iv->radio->get()) { // radio buffer empty if(!q->iv->radio->get() || ((q->iv->mGotFragment) && (0 == q->attempts))) { // radio buffer empty
cmdDone(); cmdDone();
DPRINT_IVID(DBG_INFO, q->iv->id); DPRINT_IVID(DBG_INFO, q->iv->id);
DBGPRINT(F("request timeout: ")); DBGPRINT(F("request timeout: "));
@ -127,18 +125,12 @@ class Communication : public CommQueue<> {
DBGPRINTLN(F("ms")); DBGPRINTLN(F("ms"));
if(!q->iv->mGotFragment) { if(!q->iv->mGotFragment) {
if(!testMode)
q->iv->radioStatistics.rxFailNoAnser++; // got nothing
mHeu.setGotNothing(q->iv);
if((IV_HMS == q->iv->ivGen) || (IV_HMT == q->iv->ivGen)) { if((IV_HMS == q->iv->ivGen) || (IV_HMT == q->iv->ivGen)) {
q->iv->radio->switchFrequency(q->iv, HOY_BOOT_FREQ_KHZ, (q->iv->config->frequency*FREQ_STEP_KHZ + HOY_BASE_FREQ_KHZ)); q->iv->radio->switchFrequency(q->iv, HOY_BOOT_FREQ_KHZ, (q->iv->config->frequency*FREQ_STEP_KHZ + HOY_BASE_FREQ_KHZ));
mWaitTimeout = millis() + 1000; mWaitTimeout = millis() + 1000;
} }
} else {
if(!testMode)
q->iv->radioStatistics.rxFail++;
} }
mState = States::RESET; closeRequest(q->iv, false);
break; break;
} }
@ -169,7 +161,7 @@ class Communication : public CommQueue<> {
ah::dumpBuf(p->packet, p->len); ah::dumpBuf(p->packet, p->len);
if(checkIvSerial(&p->packet[1], q->iv)) { if(checkIvSerial(&p->packet[1], q->iv)) {
if(!testMode) if(!mHeu.getTestModeEnabled())
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
@ -182,7 +174,7 @@ class Communication : public CommQueue<> {
parseMiFrame(p, q); parseMiFrame(p, q);
} }
} else { } else {
if(!testMode) if(!mHeu.getTestModeEnabled())
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;
@ -191,13 +183,9 @@ class Communication : public CommQueue<> {
q->iv->radio->mBufCtrl.pop(); q->iv->radio->mBufCtrl.pop();
yield(); yield();
} }
if(0 == q->attempts) { if((0 == q->attempts) && (!q->iv->mGotFragment))
if(!testMode) closeRequest(q->iv, false);
q->iv->radioStatistics.rxFail++; // got no complete payload else
mHeu.setGotFragment(q->iv);
cmdDone(true);
mState = States::RESET;
} else
mState = nextState; mState = nextState;
} }
@ -238,14 +226,12 @@ class Communication : public CommQueue<> {
return; return;
} }
mHeu.setGotAll(q->iv); compilePayload(q);
compilePayload(q, testMode);
if(NULL != mCbPayload) if(NULL != mCbPayload)
(mCbPayload)(q->cmd, q->iv); (mCbPayload)(q->cmd, q->iv);
cmdDone(true); // remove done request closeRequest(q->iv);
mState = States::RESET; // everything ok, next request
break; break;
} }
}); });
@ -329,7 +315,7 @@ class Communication : public CommQueue<> {
q->iv->actPowerLimit = 0xffff; // unknown, readback current value q->iv->actPowerLimit = 0xffff; // unknown, readback current value
} }
inline void compilePayload(const queue_s *q, bool testMode) { inline void compilePayload(const queue_s *q) {
uint16_t crc = 0xffff, crcRcv = 0x0000; uint16_t crc = 0xffff, crcRcv = 0x0000;
for(uint8_t i = 0; i < mMaxFrameId; i++) { for(uint8_t i = 0; i < mMaxFrameId; i++) {
if(i == (mMaxFrameId - 1)) { if(i == (mMaxFrameId - 1)) {
@ -345,7 +331,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(!testMode) 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();
} else } else
@ -391,14 +377,11 @@ class Communication : public CommQueue<> {
DPRINT(DBG_ERROR, F("plausibility check failed, expected ")); DPRINT(DBG_ERROR, F("plausibility check failed, expected "));
DBGPRINT(String(rec->pyldLen)); DBGPRINT(String(rec->pyldLen));
DBGPRINTLN(F(" bytes")); DBGPRINTLN(F(" bytes"));
if(!testMode) if(!mHeu.getTestModeEnabled())
q->iv->radioStatistics.rxFail++; q->iv->radioStatistics.rxFail++;
return; return;
} }
if(!testMode)
q->iv->radioStatistics.rxSuccess++;
rec->ts = q->ts; rec->ts = q->ts;
for (uint8_t i = 0; i < rec->length; i++) { for (uint8_t i = 0; i < rec->length; i++) {
q->iv->addValue(i, mPayload, rec); q->iv->addValue(i, mPayload, rec);
@ -426,15 +409,36 @@ class Communication : public CommQueue<> {
mWaitTimeout = millis() + SINGLEFR_TIMEOUT; // timeout mWaitTimeout = millis() + SINGLEFR_TIMEOUT; // timeout
mState = States::WAIT; mState = States::WAIT;
} else { } else {
mHeu.setGotFragment(q->iv);
q->iv->radioStatistics.rxFail++; // got no complete payload
add(q, true); add(q, true);
cmdDone(true); closeRequest(q->iv, false);
mState = States::RESET;
} }
} }
private: private:
void closeRequest(Inverter<> *iv, bool succeeded = true) {
if(succeeded) {
mHeu.setGotAll(iv);
if(!mHeu.getTestModeEnabled())
iv->radioStatistics.rxSuccess++;
cmdDone(true);
} else if(iv->mGotFragment) {
mHeu.setGotFragment(iv);
if(!mHeu.getTestModeEnabled())
iv->radioStatistics.rxFail++; // got no complete payload
cmdDone(true);
} else {
mHeu.setGotNothing(iv);
if(!mHeu.getTestModeEnabled())
iv->radioStatistics.rxFailNoAnser++; // got nothing
cmdDone();
}
iv->mGotFragment = false;
iv->mGotLastMsg = false;
iv->miMultiParts = 0;
mFirstTry = false; // for correct reset
mState = States::RESET;
}
inline void miHwDecode(packet_t *p, const queue_s *q) { inline void miHwDecode(packet_t *p, const queue_s *q) {
record_t<> *rec = q->iv->getRecordStruct(InverterDevInform_All); // choose the record structure record_t<> *rec = q->iv->getRecordStruct(InverterDevInform_All); // choose the record structure
rec->ts = q->ts; rec->ts = q->ts;
@ -545,16 +549,10 @@ class Communication : public CommQueue<> {
(mCbPayload)(InverterDevInform_Simple, q->iv); (mCbPayload)(InverterDevInform_Simple, q->iv);
q->iv->miMultiParts++; q->iv->miMultiParts++;
} }
if(q->iv->miMultiParts > 5) { if(q->iv->miMultiParts > 5)
cmdDone(true); closeRequest(q->iv, true);
mState = States::RESET; else
q->iv->radioStatistics.rxSuccess++;
mHeu.setGotAll(q->iv);
q->iv->miMultiParts = 0;
} else {
mHeu.setGotFragment(q->iv);
mState = States::WAIT; mState = States::WAIT;
}
/*if (mPayload[iv->id].multi_parts > 5) { /*if (mPayload[iv->id].multi_parts > 5) {
iv->setQueuedCmdFinished(); iv->setQueuedCmdFinished();
@ -571,7 +569,6 @@ class Communication : public CommQueue<> {
inline void miDataDecode(packet_t *p, const queue_s *q) { inline void miDataDecode(packet_t *p, const queue_s *q) {
record_t<> *rec = q->iv->getRecordStruct(RealTimeRunData_Debug); // choose the parser record_t<> *rec = q->iv->getRecordStruct(RealTimeRunData_Debug); // choose the parser
rec->ts = q->ts; rec->ts = q->ts;
q->iv->radioStatistics.rxSuccess++;
mState = States::RESET; mState = States::RESET;
uint8_t datachan = ( p->packet[0] == (MI_REQ_CH1 + ALL_FRAMES) || p->packet[0] == (MI_REQ_4CH + ALL_FRAMES) ) ? CH1 : uint8_t datachan = ( p->packet[0] == (MI_REQ_CH1 + ALL_FRAMES) || p->packet[0] == (MI_REQ_4CH + ALL_FRAMES) ) ? CH1 :
@ -613,7 +610,7 @@ class Communication : public CommQueue<> {
//mPayload[iv->id].retransmits = 0; // reserve retransmissions for each response //mPayload[iv->id].retransmits = 0; // reserve retransmissions for each response
//mPayload[iv->id].complete = false; //mPayload[iv->id].complete = false;
miNextRequest((p->packet[0] - ALL_FRAMES + 1), q); miNextRequest((p->packet[0] - ALL_FRAMES + 1), q);
mHeu.setGotFragment(q->iv); //mHeu.setGotFragment(q->iv);
} else { } else {
miComplete(q->iv); miComplete(q->iv);
} }
@ -621,7 +618,7 @@ class Communication : public CommQueue<> {
//addImportant(q->iv, MI_REQ_CH2); //addImportant(q->iv, MI_REQ_CH2);
miNextRequest(MI_REQ_CH2, q); miNextRequest(MI_REQ_CH2, q);
//use also miMultiParts here for better statistics? //use also miMultiParts here for better statistics?
mHeu.setGotFragment(q->iv); //mHeu.setGotFragment(q->iv);
} else { // first data msg for 1ch, 2nd for 2ch } else { // first data msg for 1ch, 2nd for 2ch
miComplete(q->iv); miComplete(q->iv);
} }
@ -721,7 +718,7 @@ class Communication : public CommQueue<> {
} }
inline void miComplete(Inverter<> *iv) { void miComplete(Inverter<> *iv) {
if (*mSerialDebug) { if (*mSerialDebug) {
DPRINT_IVID(DBG_INFO, iv->id); DPRINT_IVID(DBG_INFO, iv->id);
DBGPRINTLN(F("got all data msgs")); DBGPRINTLN(F("got all data msgs"));
@ -749,12 +746,14 @@ class Communication : public CommQueue<> {
// update status state-machine, // update status state-machine,
if (ac_pow) if (ac_pow)
iv->isProducing(); iv->isProducing();
mHeu.setGotAll(iv); closeRequest(iv, true);
cmdDone(true);
//mHeu.setGotAll(iv);
//cmdDone(true);
if(NULL != mCbPayload) if(NULL != mCbPayload)
(mCbPayload)(RealTimeRunData_Debug, iv); (mCbPayload)(RealTimeRunData_Debug, iv);
mState = States::RESET; // everything ok, next request //mState = States::RESET; // everything ok, next request
} }
private: private:
@ -775,7 +774,6 @@ class Communication : public CommQueue<> {
uint32_t mWaitTimeout = 0; uint32_t mWaitTimeout = 0;
uint32_t mWaitTimeout_min = 0; uint32_t mWaitTimeout_min = 0;
std::array<frame_t, MAX_PAYLOAD_ENTRIES> mLocalBuf; std::array<frame_t, MAX_PAYLOAD_ENTRIES> mLocalBuf;
//bool mGotFragment = false;
bool mFirstTry = false; bool mFirstTry = false;
uint8_t mMaxFrameId; uint8_t mMaxFrameId;
uint8_t mPayload[MAX_BUFFER]; uint8_t mPayload[MAX_BUFFER];

5
src/web/html/update.html

@ -12,9 +12,12 @@
<legend class="des">Select firmware file (*.bin)</legend> <legend class="des">Select firmware file (*.bin)</legend>
<form id="form" method="POST" action="/update" enctype="multipart/form-data" accept-charset="utf-8"> <form id="form" method="POST" action="/update" enctype="multipart/form-data" accept-charset="utf-8">
<input type="file" name="update"> <input type="file" name="update">
<input type="button" class="btn" value="Update" onclick="hide()"> <input type="button" class="btn my-4" value="Update" onclick="hide()">
</form> </form>
</fieldset> </fieldset>
<div class="row mt-4">
<a href="https://fw.ahoydtu.de" target="_blank">Download latest Release and Development verisons<a/>
</div>
</div> </div>
</div> </div>
{#HTML_FOOTER} {#HTML_FOOTER}

Loading…
Cancel
Save