mirror of https://github.com/lumapu/ahoy.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
129 lines
4.2 KiB
129 lines
4.2 KiB
//-----------------------------------------------------------------------------
|
|
// 2023 Ahoy, https://github.com/lumpapu/ahoy
|
|
// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/4.0/deed
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#ifndef __COMMUNICATION_H__
|
|
#define __COMMUNICATION_H__
|
|
|
|
#include "CommQueue.h"
|
|
#include <Arduino.h>
|
|
#include "../utils/crc.h"
|
|
|
|
class Communication : public CommQueue<> {
|
|
public:
|
|
void setup(uint32_t *timestamp) {
|
|
mTimestamp = timestamp;
|
|
}
|
|
|
|
void loop() {
|
|
get([this](bool valid, const queue_s *q) {
|
|
if(!valid)
|
|
return; // empty
|
|
|
|
switch(mState) {
|
|
case States::IDLE:
|
|
setTs(mTimestamp);
|
|
q->iv->radio->prepareDevInformCmd(q->iv, q->cmd, q->ts, q->iv->alarmLastId, false);
|
|
lastMillis = millis();
|
|
lastFound = false;
|
|
mState = States::WAIT;
|
|
break;
|
|
|
|
case States::WAIT:
|
|
if((millis()-lastMillis) < 500)
|
|
return;
|
|
mState = States::CHECK_FRAMES;
|
|
break;
|
|
|
|
case States::CHECK_FRAMES:
|
|
if(!q->iv->radio->loop())
|
|
break; // radio buffer empty
|
|
|
|
while(!q->iv->radio->mBufCtrl.empty()) {
|
|
packet_t *p = &q->iv->radio->mBufCtrl.front();
|
|
q->iv->radio->mBufCtrl.pop();
|
|
|
|
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
|
|
parseFrame(p);
|
|
else if (p->packet[0] == (TX_REQ_DEVCONTROL + ALL_FRAMES)) // response from dev control command
|
|
parseDevCtrl(p);
|
|
|
|
yield();
|
|
}
|
|
break;
|
|
}
|
|
});
|
|
}
|
|
|
|
void gotData() {
|
|
setDone();
|
|
}
|
|
|
|
private:
|
|
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;
|
|
}
|
|
|
|
inline bool checkFrameCrc(uint8_t buf[], uint8_t len) {
|
|
return (ah::crc8(buf, len - 1) == buf[len-1]);
|
|
}
|
|
|
|
inline void parseFrame(packet_t *p) {
|
|
uint8_t *frameId = &p->packet[9];
|
|
if(0x00 == *frameId)
|
|
return; // skip current packet
|
|
if((*frameId & 0x7f) > MAX_PAYLOAD_ENTRIES)
|
|
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);
|
|
if(*frameId > 0x81)
|
|
lastFound = true;
|
|
}
|
|
|
|
frame_t *f = &mLocalBuf[(*frameId & 0x7f) - 1];
|
|
memcpy(f->buf, &p->packet[10], p->len-11);
|
|
f->len = p->len - 11;
|
|
f->rssi = p->rssi;
|
|
}
|
|
|
|
inline void parseDevCtrl(packet_t *p) {
|
|
//if((p->packet[12] == ActivePowerContr) && (p->packet[13] == 0x00))
|
|
}
|
|
|
|
private:
|
|
enum class States : uint8_t {
|
|
IDLE, WAIT, CHECK_FRAMES
|
|
};
|
|
|
|
typedef struct {
|
|
uint8_t buf[MAX_RF_PAYLOAD_SIZE];
|
|
uint8_t len;
|
|
int8_t rssi;
|
|
} frame_t;
|
|
|
|
private:
|
|
States mState = States::IDLE;
|
|
uint32_t *mTimestamp;
|
|
uint32_t lastMillis;
|
|
std::array<frame_t, MAX_PAYLOAD_ENTRIES> mLocalBuf;
|
|
bool lastFound;
|
|
uint8_t maxFrameId;
|
|
};
|
|
|
|
#endif /*__COMMUNICATION_H__*/
|
|
|