|
@ -10,6 +10,9 @@ |
|
|
#include <Arduino.h> |
|
|
#include <Arduino.h> |
|
|
#include "../utils/crc.h" |
|
|
#include "../utils/crc.h" |
|
|
|
|
|
|
|
|
|
|
|
typedef std::function<void(uint8_t, Inverter<> *)> payloadListenerType; |
|
|
|
|
|
typedef std::function<void(Inverter<> *)> alarmListenerType; |
|
|
|
|
|
|
|
|
class Communication : public CommQueue<> { |
|
|
class Communication : public CommQueue<> { |
|
|
public: |
|
|
public: |
|
|
void setup(uint32_t *timestamp) { |
|
|
void setup(uint32_t *timestamp) { |
|
@ -21,6 +24,14 @@ class Communication : public CommQueue<> { |
|
|
CommQueue::addImportant(iv, cmd, delOnPop); |
|
|
CommQueue::addImportant(iv, cmd, delOnPop); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void addPayloadListener(payloadListenerType cb) { |
|
|
|
|
|
mCbPayload = cb; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void addAlarmListener(alarmListenerType cb) { |
|
|
|
|
|
mCbAlarm = cb; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
void loop() { |
|
|
void loop() { |
|
|
get([this](bool valid, const queue_s *q) { |
|
|
get([this](bool valid, const queue_s *q) { |
|
|
if(!valid) |
|
|
if(!valid) |
|
@ -45,6 +56,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); |
|
|
|
|
|
q->iv->radioStatistics.txCnt++; |
|
|
mWaitTimeout = millis() + 500; |
|
|
mWaitTimeout = millis() + 500; |
|
|
setAttempt(); |
|
|
setAttempt(); |
|
|
mState = States::WAIT; |
|
|
mState = States::WAIT; |
|
@ -59,7 +71,10 @@ class Communication : public CommQueue<> { |
|
|
case States::CHECK_FRAMES: { |
|
|
case States::CHECK_FRAMES: { |
|
|
if(!q->iv->radio->get()) { // radio buffer empty
|
|
|
if(!q->iv->radio->get()) { // radio buffer empty
|
|
|
cmdDone(); |
|
|
cmdDone(); |
|
|
DBGPRINTLN(F("request timeout")); |
|
|
DPRINT(DBG_INFO, F("request timeout: ")); |
|
|
|
|
|
DBGPRINT(String(millis() - mWaitTimeout + 500)); |
|
|
|
|
|
DBGPRINTLN(F("ms")); |
|
|
|
|
|
|
|
|
q->iv->radioStatistics.rxFailNoAnser++; // got nothing
|
|
|
q->iv->radioStatistics.rxFailNoAnser++; // got nothing
|
|
|
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, WORK_FREQ_KHZ); |
|
|
q->iv->radio->switchFrequency(q->iv, HOY_BOOT_FREQ_KHZ, WORK_FREQ_KHZ); |
|
@ -74,12 +89,14 @@ class Communication : public CommQueue<> { |
|
|
packet_t *p = &q->iv->radio->mBufCtrl.front(); |
|
|
packet_t *p = &q->iv->radio->mBufCtrl.front(); |
|
|
|
|
|
|
|
|
DPRINT_IVID(DBG_INFO, q->iv->id); |
|
|
DPRINT_IVID(DBG_INFO, q->iv->id); |
|
|
DPRINT(DBG_INFO, F("RX ")); |
|
|
DBGPRINT(F("RX ")); |
|
|
DBGPRINT(String(p->millis)); |
|
|
DBGPRINT(String(p->millis)); |
|
|
DBGPRINT(F("ms ")); |
|
|
DBGPRINT(F("ms ")); |
|
|
DBGPRINT(String(p->len)); |
|
|
DBGPRINT(String(p->len)); |
|
|
DBGPRINT(F(" CH")); |
|
|
if(IV_HM == q->iv->ivGen) { |
|
|
DBGPRINT(String(p->ch)); |
|
|
DBGPRINT(F(" CH")); |
|
|
|
|
|
DBGPRINT(String(p->ch)); |
|
|
|
|
|
} |
|
|
DBGPRINT(F(", ")); |
|
|
DBGPRINT(F(", ")); |
|
|
DBGPRINT(String(p->rssi)); |
|
|
DBGPRINT(String(p->rssi)); |
|
|
DBGPRINT(F("dBm | ")); |
|
|
DBGPRINT(F("dBm | ")); |
|
@ -91,8 +108,10 @@ class Communication : public CommQueue<> { |
|
|
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); |
|
|
parseFrame(p); |
|
|
nextState = States::CHECK_PACKAGE; |
|
|
nextState = States::CHECK_PACKAGE; |
|
|
} else if (p->packet[0] == (TX_REQ_DEVCONTROL + ALL_FRAMES)) // response from dev control command
|
|
|
} else if (p->packet[0] == (TX_REQ_DEVCONTROL + ALL_FRAMES)) { // response from dev control command
|
|
|
parseDevCtrl(p, q); |
|
|
parseDevCtrl(p, q); |
|
|
|
|
|
cmdDone(true); // remove done request
|
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
q->iv->radio->mBufCtrl.pop(); |
|
|
q->iv->radio->mBufCtrl.pop(); |
|
@ -104,26 +123,40 @@ class Communication : public CommQueue<> { |
|
|
|
|
|
|
|
|
case States::CHECK_PACKAGE: |
|
|
case States::CHECK_PACKAGE: |
|
|
if(0 == mMaxFrameId) { |
|
|
if(0 == mMaxFrameId) { |
|
|
|
|
|
setAttempt(); |
|
|
|
|
|
|
|
|
DPRINT_IVID(DBG_WARN, q->iv->id); |
|
|
DPRINT_IVID(DBG_WARN, q->iv->id); |
|
|
DBGPRINT(F("last frame missing: request retransmit")); |
|
|
DBGPRINT(F("last 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) |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
q->iv->radio->sendCmdPacket(q->iv, TX_REQ_INFO, (SINGLE_FRAME + mMaxFrameId + 1), true); |
|
|
q->iv->radio->sendCmdPacket(q->iv, TX_REQ_INFO, (ALL_FRAMES + i), true); |
|
|
setAttempt(); |
|
|
q->iv->radioStatistics.retransmits++; |
|
|
mWaitTimeout = millis() + 100; |
|
|
mWaitTimeout = millis() + 500; |
|
|
mState = States::WAIT; |
|
|
mState = States::WAIT; |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
for(uint8_t i = 0; i < mMaxFrameId; i++) { |
|
|
for(uint8_t i = 0; i < mMaxFrameId; i++) { |
|
|
if(mLocalBuf[i].len == 0) { |
|
|
if(mLocalBuf[i].len == 0) { |
|
|
|
|
|
setAttempt(); |
|
|
|
|
|
|
|
|
DPRINT_IVID(DBG_WARN, q->iv->id); |
|
|
DPRINT_IVID(DBG_WARN, q->iv->id); |
|
|
DBGPRINT(F("frame ")); |
|
|
DBGPRINT(F("frame ")); |
|
|
DBGPRINT(String(i + 1)); |
|
|
DBGPRINT(String(i + 1)); |
|
|
DBGPRINTLN(F(" missing: request retransmit")); |
|
|
DBGPRINT(F(" missing: request retransmit (")); |
|
|
|
|
|
DBGPRINT(String(q->attempts)); |
|
|
|
|
|
DBGPRINTLN(F(" attempts left)")); |
|
|
|
|
|
|
|
|
q->iv->radio->sendCmdPacket(q->iv, TX_REQ_INFO, (ALL_FRAMES + i), true); |
|
|
q->iv->radio->sendCmdPacket(q->iv, TX_REQ_INFO, (ALL_FRAMES + i), true); |
|
|
setAttempt(); |
|
|
q->iv->radioStatistics.retransmits++; |
|
|
mWaitTimeout = millis() + 100; |
|
|
mWaitTimeout = millis() + 500; |
|
|
mState = States::WAIT; |
|
|
mState = States::WAIT; |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
@ -131,6 +164,9 @@ class Communication : public CommQueue<> { |
|
|
|
|
|
|
|
|
compilePayload(q); |
|
|
compilePayload(q); |
|
|
|
|
|
|
|
|
|
|
|
if(NULL != mCbPayload) |
|
|
|
|
|
(mCbPayload)(q->cmd, q->iv); |
|
|
|
|
|
|
|
|
cmdDone(true); // remove done request
|
|
|
cmdDone(true); // remove done request
|
|
|
mState = States::RESET; // everything ok, next request
|
|
|
mState = States::RESET; // everything ok, next request
|
|
|
break; |
|
|
break; |
|
@ -194,6 +230,7 @@ class Communication : public CommQueue<> { |
|
|
DBGPRINT(String(q->iv->powerLimit[0])); |
|
|
DBGPRINT(String(q->iv->powerLimit[0])); |
|
|
DBGPRINT(F(" with PowerLimitControl ")); |
|
|
DBGPRINT(F(" with PowerLimitControl ")); |
|
|
DBGPRINTLN(String(q->iv->powerLimit[1])); |
|
|
DBGPRINTLN(String(q->iv->powerLimit[1])); |
|
|
|
|
|
q->iv->actPowerLimit = 0xffff; // unknown, readback current value
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
inline void compilePayload(const queue_s *q) { |
|
|
inline void compilePayload(const queue_s *q) { |
|
@ -220,9 +257,9 @@ class Communication : public CommQueue<> { |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
DPRINT_IVID(DBG_INFO, q->iv->id); |
|
|
/*DPRINT_IVID(DBG_INFO, q->iv->id);
|
|
|
DBGPRINT(F("procPyld: cmd: 0x")); |
|
|
DBGPRINT(F("procPyld: cmd: 0x")); |
|
|
DBGHEXLN(q->cmd); |
|
|
DBGHEXLN(q->cmd);*/ |
|
|
|
|
|
|
|
|
memset(mPayload, 0, 150); |
|
|
memset(mPayload, 0, 150); |
|
|
int8_t rssi = -127; |
|
|
int8_t rssi = -127; |
|
@ -247,6 +284,40 @@ class Communication : public CommQueue<> { |
|
|
DBGPRINT(String(len)); |
|
|
DBGPRINT(String(len)); |
|
|
DBGPRINT(F("): ")); |
|
|
DBGPRINT(F("): ")); |
|
|
ah::dumpBuf(mPayload, len); |
|
|
ah::dumpBuf(mPayload, len); |
|
|
|
|
|
|
|
|
|
|
|
record_t<> *rec = q->iv->getRecordStruct(q->cmd); |
|
|
|
|
|
if(NULL == rec) { |
|
|
|
|
|
DPRINTLN(DBG_ERROR, F("record is NULL!")); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
if((rec->pyldLen != len) && (0 != rec->pyldLen)) { |
|
|
|
|
|
DPRINT(DBG_ERROR, F("plausibility check failed, expected ")); |
|
|
|
|
|
DBGPRINT(String(rec->pyldLen)); |
|
|
|
|
|
DBGPRINTLN(F(" bytes")); |
|
|
|
|
|
q->iv->radioStatistics.rxFail++; |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
q->iv->radioStatistics.rxSuccess++; |
|
|
|
|
|
|
|
|
|
|
|
rec->ts = q->ts; |
|
|
|
|
|
for (uint8_t i = 0; i < rec->length; i++) { |
|
|
|
|
|
q->iv->addValue(i, mPayload, rec); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
q->iv->rssi = rssi; |
|
|
|
|
|
q->iv->doCalculations(); |
|
|
|
|
|
|
|
|
|
|
|
if(AlarmData == q->cmd) { |
|
|
|
|
|
uint8_t i = 0; |
|
|
|
|
|
while(1) { |
|
|
|
|
|
if(0 == q->iv->parseAlarmLog(i++, mPayload, len)) |
|
|
|
|
|
break; |
|
|
|
|
|
if (NULL != mCbAlarm) |
|
|
|
|
|
(mCbAlarm)(q->iv); |
|
|
|
|
|
yield(); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private: |
|
|
private: |
|
@ -267,6 +338,8 @@ class Communication : public CommQueue<> { |
|
|
std::array<frame_t, MAX_PAYLOAD_ENTRIES> mLocalBuf; |
|
|
std::array<frame_t, MAX_PAYLOAD_ENTRIES> mLocalBuf; |
|
|
uint8_t mMaxFrameId; |
|
|
uint8_t mMaxFrameId; |
|
|
uint8_t mPayload[150]; |
|
|
uint8_t mPayload[150]; |
|
|
|
|
|
payloadListenerType mCbPayload = NULL; |
|
|
|
|
|
alarmListenerType mCbAlarm = NULL; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
#endif /*__COMMUNICATION_H__*/ |
|
|
#endif /*__COMMUNICATION_H__*/ |
|
|