mirror of
https://github.com/lumapu/ahoy.git
synced 2025-05-18 11:26:10 +02:00
further improved new communication model
This commit is contained in:
parent
5a81a54738
commit
c7f3f21469
3 changed files with 147 additions and 30 deletions
|
@ -70,7 +70,9 @@ void app::setup() {
|
|||
else if((IV_HMS == iv->ivGen) || (IV_HMT == iv->ivGen))
|
||||
iv->radio = &mCmtRadio;
|
||||
#endif
|
||||
mCommunication.add(iv, 0x01, false);
|
||||
mCommunication.add(iv, 0x01);
|
||||
mCommunication.add(iv, 0x05);
|
||||
mCommunication.add(iv, 0x0b);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -15,13 +15,13 @@ class CommQueue {
|
|||
public:
|
||||
CommQueue() {}
|
||||
|
||||
void addImportant(Inverter<> *iv, uint8_t cmd, bool delIfFailed = true) {
|
||||
void addImportant(Inverter<> *iv, uint8_t cmd, bool delOnPop = true) {
|
||||
dec(&mRdPtr);
|
||||
mQueue[mRdPtr] = queue_s(iv, cmd, delIfFailed);
|
||||
mQueue[mRdPtr] = queue_s(iv, cmd, delOnPop);
|
||||
}
|
||||
|
||||
void add(Inverter<> *iv, uint8_t cmd, bool delIfFailed = true) {
|
||||
mQueue[mWrPtr] = queue_s(iv, cmd, delIfFailed);
|
||||
void add(Inverter<> *iv, uint8_t cmd, bool delOnPop = true) {
|
||||
mQueue[mWrPtr] = queue_s(iv, cmd, delOnPop);
|
||||
inc(&mWrPtr);
|
||||
}
|
||||
|
||||
|
@ -30,12 +30,11 @@ class CommQueue {
|
|||
Inverter<> *iv;
|
||||
uint8_t cmd;
|
||||
uint8_t attempts;
|
||||
bool delIfFailed;
|
||||
bool done;
|
||||
bool delOnPop;
|
||||
uint32_t ts;
|
||||
queue_s() {}
|
||||
queue_s(Inverter<> *i, uint8_t c, bool d) :
|
||||
iv(i), cmd(c), attempts(5), done(false), ts(0), delIfFailed(d) {}
|
||||
iv(i), cmd(c), attempts(5), ts(0), delOnPop(d) {}
|
||||
};
|
||||
|
||||
protected:
|
||||
|
@ -52,9 +51,11 @@ class CommQueue {
|
|||
cb(true, &mQueue[mRdPtr]);
|
||||
}
|
||||
|
||||
void pop(void) {
|
||||
if(!mQueue[mRdPtr].delIfFailed)
|
||||
void pop(bool force = false) {
|
||||
if(!mQueue[mRdPtr].delOnPop && !force) {
|
||||
mQueue[mRdPtr].attempts = 5;
|
||||
add(mQueue[mRdPtr]); // add to the end again
|
||||
}
|
||||
inc(&mRdPtr);
|
||||
}
|
||||
|
||||
|
@ -62,8 +63,9 @@ class CommQueue {
|
|||
mQueue[mRdPtr].ts = *ts;
|
||||
}
|
||||
|
||||
void setDone(void) {
|
||||
mQueue[mRdPtr].done = true;
|
||||
void setAttempt(void) {
|
||||
if(mQueue[mRdPtr].attempts)
|
||||
mQueue[mRdPtr].attempts--;
|
||||
}
|
||||
|
||||
void inc(uint8_t *ptr) {
|
||||
|
|
|
@ -22,49 +22,106 @@ class Communication : public CommQueue<> {
|
|||
return; // empty
|
||||
|
||||
switch(mState) {
|
||||
case States::IDLE:
|
||||
case States::RESET:
|
||||
lastFound = false;
|
||||
for(uint8_t i = 0; i < MAX_PAYLOAD_ENTRIES; i++) {
|
||||
mLocalBuf[i].len = 0;
|
||||
}
|
||||
mState = States::START;
|
||||
break;
|
||||
|
||||
case States::START:
|
||||
setTs(mTimestamp);
|
||||
q->iv->radio->prepareDevInformCmd(q->iv, q->cmd, q->ts, q->iv->alarmLastId, false);
|
||||
lastMillis = millis();
|
||||
lastFound = false;
|
||||
mWaitTimeout = millis() + 500;
|
||||
setAttempt();
|
||||
mState = States::WAIT;
|
||||
break;
|
||||
|
||||
case States::WAIT:
|
||||
if((millis()-lastMillis) < 500)
|
||||
if(millis() < mWaitTimeout)
|
||||
return;
|
||||
mState = States::CHECK_FRAMES;
|
||||
break;
|
||||
|
||||
case States::CHECK_FRAMES:
|
||||
if(!q->iv->radio->loop())
|
||||
case States::CHECK_FRAMES: {
|
||||
if(!q->iv->radio->loop()) {
|
||||
pop();
|
||||
q->iv->radioStatistics.rxFailNoAnser++; // got nothing
|
||||
mState = States::RESET;
|
||||
break; // radio buffer empty
|
||||
}
|
||||
|
||||
States nextState = States::RESET;
|
||||
while(!q->iv->radio->mBufCtrl.empty()) {
|
||||
packet_t *p = &q->iv->radio->mBufCtrl.front();
|
||||
q->iv->radio->mBufCtrl.pop();
|
||||
|
||||
DPRINT_IVID(DBG_INFO, q->iv->id);
|
||||
DPRINT(DBG_INFO, F("RX "));
|
||||
DBGPRINT(String(p->len));
|
||||
DBGPRINT(F(" CH"));
|
||||
DBGPRINT(String(p->ch));
|
||||
DBGPRINT(F(", "));
|
||||
DBGPRINT(String(p->rssi));
|
||||
DBGPRINT(F("dBm | "));
|
||||
ah::dumpBuf(p->packet, p->len);
|
||||
|
||||
if(!checkIvSerial(&p->packet[1], q->iv))
|
||||
continue; // inverter ID incorrect
|
||||
|
||||
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
|
||||
parseFrame(p);
|
||||
else if (p->packet[0] == (TX_REQ_DEVCONTROL + ALL_FRAMES)) // response from dev control command
|
||||
nextState = States::CHECK_PACKAGE;
|
||||
} else if (p->packet[0] == (TX_REQ_DEVCONTROL + ALL_FRAMES)) // response from dev control command
|
||||
parseDevCtrl(p);
|
||||
|
||||
yield();
|
||||
}
|
||||
mState = nextState;
|
||||
}
|
||||
break;
|
||||
|
||||
case States::CHECK_PACKAGE:
|
||||
if(!lastFound) {
|
||||
DPRINT_IVID(DBG_WARN, q->iv->id);
|
||||
DBGPRINT(F("last frame "));
|
||||
DBGPRINT(String(mMaxFrameId+1));
|
||||
DBGPRINTLN(F(" missing: Request Retransmit"));
|
||||
|
||||
q->iv->radio->sendCmdPacket(q->iv, TX_REQ_INFO, (SINGLE_FRAME + mMaxFrameId + 1), true);
|
||||
setAttempt();
|
||||
mWaitTimeout = millis() + 100;
|
||||
mState = States::WAIT;
|
||||
break;
|
||||
}
|
||||
|
||||
for(uint8_t i = 0; i < mMaxFrameId; i++) {
|
||||
if(mLocalBuf[i].len == 0) {
|
||||
DPRINT_IVID(DBG_WARN, q->iv->id);
|
||||
DBGPRINT(F("frame "));
|
||||
DBGPRINT(String(i + 1));
|
||||
DBGPRINTLN(F(" missing: Request Retransmit"));
|
||||
|
||||
q->iv->radio->sendCmdPacket(q->iv, TX_REQ_INFO, (SINGLE_FRAME + i), true);
|
||||
setAttempt();
|
||||
mWaitTimeout = millis() + 100;
|
||||
mState = States::WAIT;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
compilePayload(q);
|
||||
|
||||
pop(true); // remove done request
|
||||
mState = States::RESET; // everything ok, next request
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void gotData() {
|
||||
setDone();
|
||||
}
|
||||
|
||||
private:
|
||||
inline bool checkIvSerial(uint8_t buf[], Inverter<> *iv) {
|
||||
uint8_t tmp[4];
|
||||
|
@ -84,14 +141,16 @@ class Communication : public CommQueue<> {
|
|||
uint8_t *frameId = &p->packet[9];
|
||||
if(0x00 == *frameId)
|
||||
return; // skip current packet
|
||||
if((*frameId & 0x7f) > MAX_PAYLOAD_ENTRIES)
|
||||
if((*frameId & 0x7f) > MAX_PAYLOAD_ENTRIES) {
|
||||
DPRINTLN(DBG_WARN, F("local buffer to small for payload fragments!"));
|
||||
return; // local storage is to small for id
|
||||
}
|
||||
|
||||
if(!checkFrameCrc(p->packet, p->len))
|
||||
return; // CRC8 is wrong, frame invalid
|
||||
|
||||
if((*frameId & ALL_FRAMES) == ALL_FRAMES) {
|
||||
maxFrameId = (*frameId & 0x7f);
|
||||
mMaxFrameId = (*frameId & 0x7f);
|
||||
if(*frameId > 0x81)
|
||||
lastFound = true;
|
||||
}
|
||||
|
@ -106,9 +165,62 @@ class Communication : public CommQueue<> {
|
|||
//if((p->packet[12] == ActivePowerContr) && (p->packet[13] == 0x00))
|
||||
}
|
||||
|
||||
inline void compilePayload(const queue_s *q) {
|
||||
uint16_t crc = 0xffff, crcRcv = 0x0000;
|
||||
for(uint8_t i = 0; i < mMaxFrameId; i++) {
|
||||
if(i == (mMaxFrameId - 1)) {
|
||||
crc = ah::crc16(mLocalBuf[i].buf, mLocalBuf[i].len - 2, crc);
|
||||
crcRcv = (mLocalBuf[i].buf[mLocalBuf[i].len-2] << 8);
|
||||
crcRcv |= mLocalBuf[i].buf[mLocalBuf[i].len-1];
|
||||
} else
|
||||
crc = ah::crc16(mLocalBuf[i].buf, mLocalBuf[i].len, crc);
|
||||
}
|
||||
|
||||
if(crc != crcRcv) {
|
||||
DPRINT_IVID(DBG_WARN, q->iv->id);
|
||||
DBGPRINT(F("CRC Error "));
|
||||
if(q->attempts == 0) {
|
||||
DBGPRINTLN(F("-> Fail"));
|
||||
q->iv->radioStatistics.rxFail++; // got fragments but not complete response
|
||||
pop();
|
||||
} else
|
||||
DBGPRINTLN(F("-> complete retransmit"));
|
||||
mState = States::RESET;
|
||||
return;
|
||||
}
|
||||
|
||||
DPRINT_IVID(DBG_INFO, q->iv->id);
|
||||
DBGPRINT(F("procPyld: cmd: 0x"));
|
||||
DBGHEXLN(q->cmd);
|
||||
|
||||
memset(mPayload, 0, 150);
|
||||
int8_t rssi = -127;
|
||||
uint8_t len = 0;
|
||||
|
||||
for(uint8_t i = 0; i < mMaxFrameId; i++) {
|
||||
if(mLocalBuf[i].len + len > 150) {
|
||||
DPRINTLN(DBG_ERROR, F("payload buffer to small!"));
|
||||
return;
|
||||
}
|
||||
memcpy(&mPayload[len], mLocalBuf[i].buf, mLocalBuf[i].len);
|
||||
len += mLocalBuf[i].len;
|
||||
// get worst RSSI
|
||||
if(mLocalBuf[i].rssi > rssi)
|
||||
rssi = mLocalBuf[i].rssi;
|
||||
}
|
||||
|
||||
len -= 2;
|
||||
|
||||
DPRINT_IVID(DBG_INFO, q->iv->id);
|
||||
DBGPRINT(F("Payload ("));
|
||||
DBGPRINT(String(len));
|
||||
DBGPRINT(F("): "));
|
||||
ah::dumpBuf(mPayload, len);
|
||||
}
|
||||
|
||||
private:
|
||||
enum class States : uint8_t {
|
||||
IDLE, WAIT, CHECK_FRAMES
|
||||
RESET, START, WAIT, CHECK_FRAMES, CHECK_PACKAGE
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
|
@ -118,12 +230,13 @@ class Communication : public CommQueue<> {
|
|||
} frame_t;
|
||||
|
||||
private:
|
||||
States mState = States::IDLE;
|
||||
States mState = States::RESET;
|
||||
uint32_t *mTimestamp;
|
||||
uint32_t lastMillis;
|
||||
uint32_t mWaitTimeout;
|
||||
std::array<frame_t, MAX_PAYLOAD_ENTRIES> mLocalBuf;
|
||||
bool lastFound;
|
||||
uint8_t maxFrameId;
|
||||
uint8_t mMaxFrameId;
|
||||
uint8_t mPayload[150];
|
||||
};
|
||||
|
||||
#endif /*__COMMUNICATION_H__*/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue