|
|
@ -10,8 +10,9 @@ |
|
|
|
#include <Arduino.h> |
|
|
|
#include "../utils/crc.h" |
|
|
|
|
|
|
|
#define MI_TIMEOUT 500 |
|
|
|
#define MI_TIMEOUT 250 |
|
|
|
#define DEFAULT_TIMEOUT 500 |
|
|
|
#define MAX_BUFFER 200 //was: 150 (hardcoded)
|
|
|
|
|
|
|
|
typedef std::function<void(uint8_t, Inverter<> *)> payloadListenerType; |
|
|
|
typedef std::function<void(Inverter<> *)> alarmListenerType; |
|
|
@ -40,7 +41,7 @@ class Communication : public CommQueue<> { |
|
|
|
if(!valid) |
|
|
|
return; // empty
|
|
|
|
|
|
|
|
uint16_t lcl_tmo = q->iv->ivGen != IV_MI ? DEFAULT_TIMEOUT : MI_TIMEOUT; |
|
|
|
uint16_t timeout = q->iv->ivGen != IV_MI ? DEFAULT_TIMEOUT : MI_TIMEOUT; |
|
|
|
|
|
|
|
switch(mState) { |
|
|
|
case States::RESET: |
|
|
@ -59,22 +60,10 @@ class Communication : public CommQueue<> { |
|
|
|
if(ActivePowerContr == q->cmd) |
|
|
|
q->iv->powerLimitAck = false; |
|
|
|
q->iv->radio->sendControlPacket(q->iv, q->cmd, q->iv->powerLimit, false); |
|
|
|
} |
|
|
|
else if (q->iv->ivGen != IV_MI) |
|
|
|
} else |
|
|
|
q->iv->radio->prepareDevInformCmd(q->iv, q->cmd, q->ts, q->iv->alarmLastId, false); |
|
|
|
else { // IV_MI
|
|
|
|
//uint8_t cmd = q->iv->type == INV_TYPE_4CH ? MI_REQ_4CH : MI_REQ_CH1;
|
|
|
|
//q->iv->radio->sendCmdPacket(q->iv, cmd, cmd, false, false);
|
|
|
|
q->iv->radio->sendCmdPacket(q->iv, q->cmd, q->cmd, false, false); |
|
|
|
//if (q->iv->radio->mSerialDebug) {
|
|
|
|
DPRINT_IVID(DBG_INFO, q->iv->id); |
|
|
|
DBGPRINT(F("legacy cmd 0x")); |
|
|
|
DBGHEXLN(q->cmd); |
|
|
|
//}
|
|
|
|
//mPayload[q->iv->id]. = cmd;
|
|
|
|
} |
|
|
|
q->iv->radioStatistics.txCnt++; |
|
|
|
mWaitTimeout = millis() + lcl_tmo; |
|
|
|
mWaitTimeout = millis() + timeout; |
|
|
|
setAttempt(); |
|
|
|
mState = States::WAIT; |
|
|
|
break; |
|
|
@ -90,7 +79,7 @@ class Communication : public CommQueue<> { |
|
|
|
cmdDone(); |
|
|
|
DPRINT_IVID(DBG_INFO, q->iv->id); |
|
|
|
DBGPRINT(F("request timeout: ")); |
|
|
|
DBGPRINT(String(millis() - mWaitTimeout + lcl_tmo)); |
|
|
|
DBGPRINT(String(millis() - mWaitTimeout + timeout)); |
|
|
|
DBGPRINTLN(F("ms")); |
|
|
|
|
|
|
|
q->iv->radioStatistics.rxFailNoAnser++; // got nothing
|
|
|
@ -109,16 +98,15 @@ class Communication : public CommQueue<> { |
|
|
|
DPRINT_IVID(DBG_INFO, q->iv->id); |
|
|
|
DBGPRINT(F("RX ")); |
|
|
|
if(p->millis < 100) |
|
|
|
DBGPRINT(F("0")); |
|
|
|
DBGPRINT(F(" ")); |
|
|
|
DBGPRINT(String(p->millis)); |
|
|
|
DBGPRINT(F("ms ")); |
|
|
|
DBGPRINT(String(p->len)); |
|
|
|
if((IV_HM == q->iv->ivGen) || (IV_MI == q->iv->ivGen)) { |
|
|
|
DBGPRINT(F(" CH")); |
|
|
|
if(3 == p->ch) |
|
|
|
DBGPRINT(F("03")); |
|
|
|
else |
|
|
|
DBGPRINT(String(p->ch)); |
|
|
|
DBGPRINT(F("0")); |
|
|
|
DBGPRINT(String(p->ch)); |
|
|
|
} |
|
|
|
DBGPRINT(F(", ")); |
|
|
|
DBGPRINT(String(p->rssi)); |
|
|
@ -137,13 +125,20 @@ class Communication : public CommQueue<> { |
|
|
|
} else if(IV_MI == q->iv->ivGen) { |
|
|
|
parseMiFrame(p, q); |
|
|
|
} |
|
|
|
} else |
|
|
|
} else { |
|
|
|
DPRINTLN(DBG_WARN, F("Inverter serial does not match")); |
|
|
|
mWaitTimeout = millis() + timeout; |
|
|
|
} |
|
|
|
|
|
|
|
q->iv->radio->mBufCtrl.pop(); |
|
|
|
yield(); |
|
|
|
} |
|
|
|
mState = nextState; |
|
|
|
if(0 == q->attempts) { |
|
|
|
cmdDone(q); |
|
|
|
mState = States::RESET; |
|
|
|
} else |
|
|
|
mState = nextState; |
|
|
|
|
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
@ -158,14 +153,15 @@ class Communication : public CommQueue<> { |
|
|
|
|
|
|
|
uint8_t i = 0; |
|
|
|
while(i < MAX_PAYLOAD_ENTRIES) { |
|
|
|
if(mLocalBuf[i++].len == 0) |
|
|
|
if(mLocalBuf[i].len == 0) |
|
|
|
break; |
|
|
|
i++; |
|
|
|
} |
|
|
|
|
|
|
|
if(q->attempts) { |
|
|
|
q->iv->radio->sendCmdPacket(q->iv, TX_REQ_INFO, (ALL_FRAMES + i), true); |
|
|
|
q->iv->radio->sendCmdPacket(q->iv, TX_REQ_INFO, (SINGLE_FRAME + i), true); |
|
|
|
q->iv->radioStatistics.retransmits++; |
|
|
|
mWaitTimeout = millis() + lcl_tmo; |
|
|
|
mWaitTimeout = millis() + timeout; |
|
|
|
mState = States::WAIT; |
|
|
|
} else { |
|
|
|
add(q, true); |
|
|
@ -187,9 +183,9 @@ class Communication : public CommQueue<> { |
|
|
|
DBGPRINTLN(F(" attempts left)")); |
|
|
|
|
|
|
|
if(q->attempts) { |
|
|
|
q->iv->radio->sendCmdPacket(q->iv, TX_REQ_INFO, (ALL_FRAMES + i), true); |
|
|
|
q->iv->radio->sendCmdPacket(q->iv, TX_REQ_INFO, (SINGLE_FRAME + i), true); |
|
|
|
q->iv->radioStatistics.retransmits++; |
|
|
|
mWaitTimeout = millis() + lcl_tmo; |
|
|
|
mWaitTimeout = millis() + timeout; |
|
|
|
mState = States::WAIT; |
|
|
|
} else { |
|
|
|
add(q, true); |
|
|
@ -257,65 +253,165 @@ class Communication : public CommQueue<> { |
|
|
|
|| (p->packet[0] == MI_REQ_CH2 + ALL_FRAMES) |
|
|
|
|| ((p->packet[0] >= (MI_REQ_4CH + ALL_FRAMES)) |
|
|
|
&& (p->packet[0] < (0x39 + SINGLE_FRAME)) |
|
|
|
&& (q->cmd != 0x0f))) { |
|
|
|
)) { //&& (p->packet[0] != (0x0f + ALL_FRAMES)))) {
|
|
|
|
// small MI or MI 1500 data responses to 0x09, 0x11, 0x36, 0x37, 0x38 and 0x39
|
|
|
|
//mPayload[iv->id].txId = p->packet[0];
|
|
|
|
miDataDecode(p, q); |
|
|
|
|
|
|
|
} |
|
|
|
else if (p->packet[0] == 0x0f + ALL_FRAMES) |
|
|
|
} else if (p->packet[0] == (0x0f + ALL_FRAMES)) |
|
|
|
miHwDecode(p, q); |
|
|
|
|
|
|
|
else if ((p->packet[0] == 0x88) || (p->packet[0] == 0x92)) { |
|
|
|
record_t<> *rec = q->iv->getRecordStruct(RealTimeRunData_Debug); // choose the record structure
|
|
|
|
rec->ts = q->ts; |
|
|
|
miStsConsolidate(q, p->packet[0] == 0x88 ? 1 : 2, rec, p->packet[10], p->packet[12], p->packet[9], p->packet[11]); |
|
|
|
miStsConsolidate(q, ((p->packet[0] == 0x88) ? 1 : 2), rec, p->packet[10], p->packet[12], p->packet[9], p->packet[11]); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
inline void parseDevCtrl(packet_t *p, const queue_s *q) { |
|
|
|
if((p->packet[12] != ActivePowerContr) || (p->packet[13] != 0x00)) |
|
|
|
return; |
|
|
|
bool accepted = true; |
|
|
|
if((p->packet[10] == 0x00) && (p->packet[11] == 0x00)) |
|
|
|
q->iv->powerLimitAck = true; |
|
|
|
else |
|
|
|
accepted = false; |
|
|
|
|
|
|
|
DPRINT_IVID(DBG_INFO, q->iv->id); |
|
|
|
DBGPRINT(F(" has ")); |
|
|
|
if(!accepted) DBGPRINT(F("not ")); |
|
|
|
DBGPRINT(F("accepted power limit set point ")); |
|
|
|
DBGPRINT(String(q->iv->powerLimit[0])); |
|
|
|
DBGPRINT(F(" with PowerLimitControl ")); |
|
|
|
DBGPRINTLN(String(q->iv->powerLimit[1])); |
|
|
|
q->iv->actPowerLimit = 0xffff; // unknown, readback current value
|
|
|
|
} |
|
|
|
|
|
|
|
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
|
|
|
|
cmdDone(); |
|
|
|
} 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, MAX_BUFFER); |
|
|
|
int8_t rssi = -127; |
|
|
|
uint8_t len = 0; |
|
|
|
|
|
|
|
for(uint8_t i = 0; i < mMaxFrameId; i++) { |
|
|
|
if(mLocalBuf[i].len + len > MAX_BUFFER) { |
|
|
|
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 (high value is better)
|
|
|
|
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); |
|
|
|
|
|
|
|
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: |
|
|
|
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 |
|
|
|
byte[0] byte[1] byte[2] byte[3] byte[4] byte[5] byte[6] byte[7] byte[8] byte[9] byte[10] byte[11] byte[12] |
|
|
|
0x7e 0x0f xx xx xx xx YY YY YY YY 0x00 CRC 0x7f |
|
|
|
Command Receipt - First Frame |
|
|
|
start byte Command word target address routing address Multi-frame marking User data User data User data User data User data User data User data User data User data User data User data User data User data User data User data User data check end byte |
|
|
|
byte[0] byte[1] byte[2] byte[3] byte[4] byte[5] byte[6] byte[7] byte[8] byte[9] byte[10] byte[11] byte[12] byte[13] byte[14] byte[15] byte[16] byte[17] byte[18] byte[19] byte[20] byte[21] byte[22] byte[23] byte[24] byte[25] byte[26] byte[27] byte[28] |
|
|
|
0x7e 0x8f YY YY YY YY xx xx xx xx 0x00 USFWBuild_VER APPFWBuild_VER APPFWBuild_YYYY APPFWBuild_MMDD APPFWBuild_HHMM APPFW_PN HW_VER CRC 0x7f |
|
|
|
Command Receipt - Second Frame |
|
|
|
start byte Command word target address routing address Multi-frame marking User data User data User data User data User data User data User data User data User data User data User data User data User data User data User data User data check end byte |
|
|
|
byte[0] byte[1] byte[2] byte[3] byte[4] byte[5] byte[6] byte[7] byte[8] byte[9] byte[10] byte[11] byte[12] byte[13] byte[14] byte[15] byte[16] byte[17] byte[18] byte[19] byte[20] byte[21] byte[22] byte[23] byte[24] byte[25] byte[26] byte[27] byte[28] |
|
|
|
0x7e 0x8f YY YY YY YY xx xx xx xx 0x01 HW_PN HW_FB_TLmValue HW_FB_ReSPRT HW_GridSamp_ResValule HW_ECapValue Matching_APPFW_PN CRC 0x7f |
|
|
|
Command receipt - third frame |
|
|
|
start byte Command word target address routing address Multi-frame marking User data User data User data User data User data User data User data User data check end byte |
|
|
|
byte[0] byte[1] byte[2] byte[3] byte[4] byte[5] byte[6] byte[7] byte[8] byte[9] byte[10] byte[11] byte[12] byte[13] byte[14] byte[15] byte[16] byte[15] byte[16] byte[17] byte[18] |
|
|
|
0x7e 0x8f YY YY YY YY xx xx xx xx 0x12 APPFW_MINVER HWInfoAddr PNInfoCRC_gusv PNInfoCRC_gusv CRC 0x7f |
|
|
|
*/ |
|
|
|
|
|
|
|
/*
|
|
|
|
case InverterDevInform_All: |
|
|
|
rec->length = (uint8_t)(HMINFO_LIST_LEN); |
|
|
|
rec->assign = (byteAssign_t *)InfoAssignment; |
|
|
|
rec->pyldLen = HMINFO_PAYLOAD_LEN; |
|
|
|
break; |
|
|
|
|
|
|
|
const byteAssign_t InfoAssignment[] = { |
|
|
|
{ FLD_FW_VERSION, UNIT_NONE, CH0, 0, 2, 1 }, |
|
|
|
{ FLD_FW_BUILD_YEAR, UNIT_NONE, CH0, 2, 2, 1 }, |
|
|
|
{ FLD_FW_BUILD_MONTH_DAY, UNIT_NONE, CH0, 4, 2, 1 }, |
|
|
|
{ FLD_FW_BUILD_HOUR_MINUTE, UNIT_NONE, CH0, 6, 2, 1 }, |
|
|
|
{ FLD_BOOTLOADER_VER, UNIT_NONE, CH0, 8, 2, 1 } |
|
|
|
}; |
|
|
|
*/ |
|
|
|
|
|
|
|
/*
|
|
|
|
Polling the device software and hardware version number command |
|
|
|
start byte Command word routing address target address User data check end byte |
|
|
|
byte[0] byte[1] byte[2] byte[3] byte[4] byte[5] byte[6] byte[7] byte[8] byte[9] byte[10] byte[11] byte[12] |
|
|
|
0x7e 0x0f xx xx xx xx YY YY YY YY 0x00 CRC 0x7f |
|
|
|
Command Receipt - First Frame |
|
|
|
start byte Command word target address routing address Multi-frame marking User data User data User data User data User data User data User data User data User data User data User data User data User data User data User data User data check end byte |
|
|
|
byte[0] byte[1] byte[2] byte[3] byte[4] byte[5] byte[6] byte[7] byte[8] byte[9] byte[10] byte[11] byte[12] byte[13] byte[14] byte[15] byte[16] byte[17] byte[18] byte[19] byte[20] byte[21] byte[22] byte[23] byte[24] byte[25] byte[26] byte[27] byte[28] |
|
|
|
0x7e 0x8f YY YY YY YY xx xx xx xx 0x00 USFWBuild_VER APPFWBuild_VER APPFWBuild_YYYY APPFWBuild_MMDD APPFWBuild_HHMM APPFW_PN HW_VER CRC 0x7f |
|
|
|
Command Receipt - Second Frame |
|
|
|
start byte Command word target address routing address Multi-frame marking User data User data User data User data User data User data User data User data User data User data User data User data User data User data User data User data check end byte |
|
|
|
byte[0] byte[1] byte[2] byte[3] byte[4] byte[5] byte[6] byte[7] byte[8] byte[9] byte[10] byte[11] byte[12] byte[13] byte[14] byte[15] byte[16] byte[17] byte[18] byte[19] byte[20] byte[21] byte[22] byte[23] byte[24] byte[25] byte[26] byte[27] byte[28] |
|
|
|
0x7e 0x8f YY YY YY YY xx xx xx xx 0x01 HW_PN HW_FB_TLmValue HW_FB_ReSPRT HW_GridSamp_ResValule HW_ECapValue Matching_APPFW_PN CRC 0x7f |
|
|
|
Command receipt - third frame |
|
|
|
start byte Command word target address routing address Multi-frame marking User data User data User data User data User data User data User data User data check end byte |
|
|
|
byte[0] byte[1] byte[2] byte[3] byte[4] byte[5] byte[6] byte[7] byte[8] byte[9] byte[10] byte[11] byte[12] byte[13] byte[14] byte[15] byte[16] byte[15] byte[16] byte[17] byte[18] |
|
|
|
0x7e 0x8f YY YY YY YY xx xx xx xx 0x12 APPFW_MINVER HWInfoAddr PNInfoCRC_gusv PNInfoCRC_gusv CRC 0x7f |
|
|
|
*/ |
|
|
|
|
|
|
|
/*
|
|
|
|
case InverterDevInform_All: |
|
|
|
rec->length = (uint8_t)(HMINFO_LIST_LEN); |
|
|
|
rec->assign = (byteAssign_t *)InfoAssignment; |
|
|
|
rec->pyldLen = HMINFO_PAYLOAD_LEN; |
|
|
|
break; |
|
|
|
const byteAssign_t InfoAssignment[] = { |
|
|
|
{ FLD_FW_VERSION, UNIT_NONE, CH0, 0, 2, 1 }, |
|
|
|
{ FLD_FW_BUILD_YEAR, UNIT_NONE, CH0, 2, 2, 1 }, |
|
|
|
{ FLD_FW_BUILD_MONTH_DAY, UNIT_NONE, CH0, 4, 2, 1 }, |
|
|
|
{ FLD_FW_BUILD_HOUR_MINUTE, UNIT_NONE, CH0, 6, 2, 1 }, |
|
|
|
{ FLD_BOOTLOADER_VER, UNIT_NONE, CH0, 8, 2, 1 } |
|
|
|
}; |
|
|
|
*/ |
|
|
|
if ( p->packet[9] == 0x00 ) {//first frame
|
|
|
|
//FLD_FW_VERSION
|
|
|
|
for (uint8_t i = 0; i < 5; i++) { |
|
|
@ -413,9 +509,6 @@ const byteAssign_t InfoAssignment[] = { |
|
|
|
q->iv->radioStatistics.rxSuccess++; |
|
|
|
mState = States::RESET; |
|
|
|
|
|
|
|
//mPayload[iv->id].gotFragment = true;
|
|
|
|
//mPayload[iv->id].multi_parts += 4;
|
|
|
|
|
|
|
|
uint8_t datachan = ( p->packet[0] == (MI_REQ_CH1 + ALL_FRAMES) || p->packet[0] == (MI_REQ_4CH + ALL_FRAMES) ) ? CH1 : |
|
|
|
( p->packet[0] == (MI_REQ_CH2 + ALL_FRAMES) || p->packet[0] == (0x37 + ALL_FRAMES) ) ? CH2 : |
|
|
|
p->packet[0] == (0x38 + ALL_FRAMES) ? CH3 : |
|
|
@ -434,18 +527,13 @@ const byteAssign_t InfoAssignment[] = { |
|
|
|
|
|
|
|
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;
|
|
|
|
q->iv->rssi = p->rssi; |
|
|
|
else if(q->iv->rssi > p->rssi) |
|
|
|
q->iv->rssi = p->rssi; |
|
|
|
|
|
|
|
/*if ( datachan < 3 ) {
|
|
|
|
mPayload[q->iv->id].dataAB[datachan] = true; |
|
|
|
} |
|
|
|
if ( !mPayload[iv->id].dataAB[CH0] && mPayload[iv->id].dataAB[CH1] && mPayload[iv->id].dataAB[CH2] ) { |
|
|
|
mPayload[iv->id].dataAB[CH0] = true; |
|
|
|
}*/ |
|
|
|
|
|
|
|
if (p->packet[0] >= (MI_REQ_4CH + ALL_FRAMES) ) { |
|
|
|
/*For MI1500:
|
|
|
|
if (MI1500) { |
|
|
@ -453,14 +541,19 @@ const byteAssign_t InfoAssignment[] = { |
|
|
|
FCNT = (uint8_t)(p->packet[26]); |
|
|
|
FCODE = (uint8_t)(p->packet[27]); |
|
|
|
}*/ |
|
|
|
miStsConsolidate(q, datachan, rec, p->packet[23], p->packet[24]); |
|
|
|
miStsConsolidate(q, datachan, rec, p->packet[23], p->packet[24]); |
|
|
|
|
|
|
|
if (p->packet[0] < (0x39 + ALL_FRAMES) ) { |
|
|
|
addImportant(q->iv, (q->cmd + 1)); |
|
|
|
//mPayload[iv->id].txCmd++;
|
|
|
|
//mPayload[iv->id].retransmits = 0; // reserve retransmissions for each response
|
|
|
|
//mPayload[iv->id].complete = false;
|
|
|
|
miNextRequest((p->packet[0] - ALL_FRAMES + 1), q); |
|
|
|
} else { |
|
|
|
miComplete(q->iv); |
|
|
|
} |
|
|
|
} else if((p->packet[0] == (MI_REQ_CH1 + ALL_FRAMES)) && q->iv->type == INV_TYPE_2CH ) { |
|
|
|
} 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); |
|
|
|
} else { // first data msg for 1ch, 2nd for 2ch
|
|
|
|
miComplete(q->iv); |
|
|
@ -488,17 +581,6 @@ const byteAssign_t InfoAssignment[] = { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/* inline void miStsDecode(Inverter<> *iv, packet_t *p, uint8_t stschan = CH1) {
|
|
|
|
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); // choose the record structure
|
|
|
|
rec->ts = mPayload[iv->id].ts; |
|
|
|
mPayload[iv->id].gotFragment = true; |
|
|
|
mPayload[iv->id].multi_parts += 3; |
|
|
|
mPayload[iv->id].txId = p->packet[0]; |
|
|
|
miStsConsolidate(iv, stschan, rec, p->packet[10], p->packet[12], p->packet[9], p->packet[11]); |
|
|
|
mPayload[iv->id].stsAB[stschan] = true; |
|
|
|
if (mPayload[iv->id].stsAB[CH1] && mPayload[iv->id].stsAB[CH2]) |
|
|
|
*/ |
|
|
|
|
|
|
|
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) { |
|
|
|
//uint8_t status = (p->packet[11] << 8) + p->packet[12];
|
|
|
|
uint16_t statusMi = 3; // regular status for MI, change to 1 later?
|
|
|
@ -598,113 +680,6 @@ const byteAssign_t InfoAssignment[] = { |
|
|
|
iv->isProducing(); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
inline void parseDevCtrl(packet_t *p, const queue_s *q) { |
|
|
|
if((p->packet[12] != ActivePowerContr) || (p->packet[13] != 0x00)) |
|
|
|
return; |
|
|
|
bool accepted = true; |
|
|
|
if((p->packet[10] == 0x00) && (p->packet[11] == 0x00)) |
|
|
|
q->iv->powerLimitAck = true; |
|
|
|
else |
|
|
|
accepted = false; |
|
|
|
|
|
|
|
DPRINT_IVID(DBG_INFO, q->iv->id); |
|
|
|
DBGPRINT(F("has ")); |
|
|
|
if(!accepted) DBGPRINT(F("not ")); |
|
|
|
DBGPRINT(F("accepted power limit set point ")); |
|
|
|
DBGPRINT(String(q->iv->powerLimit[0])); |
|
|
|
DBGPRINT(F(" with PowerLimitControl ")); |
|
|
|
DBGPRINTLN(String(q->iv->powerLimit[1])); |
|
|
|
q->iv->actPowerLimit = 0xffff; // unknown, readback current value
|
|
|
|
} |
|
|
|
|
|
|
|
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
|
|
|
|
cmdDone(); |
|
|
|
} 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 best 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); |
|
|
|
|
|
|
|
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: |
|
|
|
enum class States : uint8_t { |
|
|
|
RESET, START, WAIT, CHECK_FRAMES, CHECK_PACKAGE |
|
|
@ -722,7 +697,7 @@ const byteAssign_t InfoAssignment[] = { |
|
|
|
uint32_t mWaitTimeout = 0; |
|
|
|
std::array<frame_t, MAX_PAYLOAD_ENTRIES> mLocalBuf; |
|
|
|
uint8_t mMaxFrameId; |
|
|
|
uint8_t mPayload[150]; |
|
|
|
uint8_t mPayload[MAX_BUFFER]; |
|
|
|
payloadListenerType mCbPayload = NULL; |
|
|
|
alarmListenerType mCbAlarm = NULL; |
|
|
|
}; |
|
|
|