|
@ -25,7 +25,6 @@ typedef struct { |
|
|
uint8_t txId; |
|
|
uint8_t txId; |
|
|
uint8_t invId; |
|
|
uint8_t invId; |
|
|
uint8_t retransmits; |
|
|
uint8_t retransmits; |
|
|
//uint8_t skipfirstrepeat;
|
|
|
|
|
|
bool gotFragment; |
|
|
bool gotFragment; |
|
|
/*
|
|
|
/*
|
|
|
uint8_t data[MAX_PAYLOAD_ENTRIES][MAX_RF_PAYLOAD_SIZE]; |
|
|
uint8_t data[MAX_PAYLOAD_ENTRIES][MAX_RF_PAYLOAD_SIZE]; |
|
@ -70,8 +69,8 @@ class MiPayload { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void loop() { |
|
|
void loop() { |
|
|
if(NULL != mHighPrioIv) { // && mHighPrioIv->ivGen == IV_MI) {
|
|
|
if ( NULL != mHighPrioIv && mHighPrioIv->ivGen == IV_MI ) { |
|
|
ivSend(mHighPrioIv, true); // for devcontrol commands?
|
|
|
ivSend(mHighPrioIv, true); // for e.g. devcontrol commands
|
|
|
mHighPrioIv = NULL; |
|
|
mHighPrioIv = NULL; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
@ -87,22 +86,24 @@ class MiPayload { |
|
|
process(false); // no retransmit
|
|
|
process(false); // no retransmit
|
|
|
|
|
|
|
|
|
if (!mPayload[iv->id].complete) { |
|
|
if (!mPayload[iv->id].complete) { |
|
|
if (!mPayload[iv->id].gotFragment) |
|
|
|
|
|
mStat->rxFailNoAnser++; // got nothing
|
|
|
|
|
|
else |
|
|
|
|
|
mStat->rxFail++; // got fragments but not complete response
|
|
|
|
|
|
|
|
|
|
|
|
iv->setQueuedCmdFinished(); // command failed
|
|
|
|
|
|
if (mSerialDebug) |
|
|
if (mSerialDebug) |
|
|
DPRINT_IVID(DBG_INFO, iv->id); |
|
|
DPRINT_IVID(DBG_INFO, iv->id); |
|
|
|
|
|
if (!mPayload[iv->id].gotFragment) { |
|
|
|
|
|
mStat->rxFailNoAnser++; // got nothing
|
|
|
|
|
|
if (mSerialDebug) |
|
|
DBGPRINTLN(F("enqueued cmd failed/timeout")); |
|
|
DBGPRINTLN(F("enqueued cmd failed/timeout")); |
|
|
|
|
|
} |
|
|
|
|
|
else { |
|
|
|
|
|
mStat->rxFail++; // got "fragments" (part of the required messages)
|
|
|
|
|
|
// but no complete set of responses
|
|
|
if (mSerialDebug) { |
|
|
if (mSerialDebug) { |
|
|
DPRINT_IVID(DBG_INFO, iv->id); |
|
|
DBGPRINT(F("no complete Payload received! (retransmits: ")); |
|
|
DBGPRINT(F("no Payload received! (retransmits: ")); |
|
|
|
|
|
DBGPRINT(String(mPayload[iv->id].retransmits)); |
|
|
DBGPRINT(String(mPayload[iv->id].retransmits)); |
|
|
DBGPRINTLN(F(")")); |
|
|
DBGPRINTLN(F(")")); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
iv->setQueuedCmdFinished(); // command failed
|
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -232,42 +233,39 @@ const byteAssign_t InfoAssignment[] = { |
|
|
iv->setValue(i, rec, (float) ((p->packet[(12+2*i)] << 8) + p->packet[(13+2*i)])/1); |
|
|
iv->setValue(i, rec, (float) ((p->packet[(12+2*i)] << 8) + p->packet[(13+2*i)])/1); |
|
|
} |
|
|
} |
|
|
iv->isConnected = true; |
|
|
iv->isConnected = true; |
|
|
|
|
|
mPayload[iv->id].gotFragment = true; |
|
|
if(mSerialDebug) { |
|
|
if(mSerialDebug) { |
|
|
DPRINT_IVID(DBG_INFO, iv->id); |
|
|
DPRINT_IVID(DBG_INFO, iv->id); |
|
|
DPRINT(DBG_INFO,F("HW_VER is ")); |
|
|
DPRINT(DBG_INFO,F("HW_VER is ")); |
|
|
DBGPRINTLN(String((p->packet[24] << 8) + p->packet[25])); |
|
|
DBGPRINTLN(String((p->packet[24] << 8) + p->packet[25])); |
|
|
} |
|
|
} |
|
|
/*iv->setQueuedCmdFinished();
|
|
|
|
|
|
mSys->Radio.sendCmdPacket(iv->radioId.u64, 0x0f, 0x01, false);*/ |
|
|
|
|
|
} else if ( p->packet[9] == 0x01 || p->packet[9] == 0x10 ) {//second frame for MI, 3rd gen. answers in 0x10
|
|
|
} else if ( p->packet[9] == 0x01 || p->packet[9] == 0x10 ) {//second frame for MI, 3rd gen. answers in 0x10
|
|
|
DPRINT_IVID(DBG_INFO, iv->id); |
|
|
DPRINT_IVID(DBG_INFO, iv->id); |
|
|
if ( p->packet[9] == 0x01 ) { |
|
|
if ( p->packet[9] == 0x01 ) { |
|
|
DBGPRINTLN(F("got 2nd frame (hw info)")); |
|
|
DBGPRINTLN(F("got 2nd frame (hw info)")); |
|
|
} else { |
|
|
|
|
|
DBGPRINTLN(F("3rd gen. inverter!")); // see table in OpenDTU code, DevInfoParser.cpp devInfo[]
|
|
|
|
|
|
} |
|
|
|
|
|
// xlsx: HW_ECapValue is total energy?!? (data coll. inst. #154)
|
|
|
|
|
|
DPRINT(DBG_INFO,F("HW_PartNo ")); |
|
|
DPRINT(DBG_INFO,F("HW_PartNo ")); |
|
|
DBGPRINTLN(String((uint32_t) (((p->packet[10] << 8) | p->packet[11]) << 8 | p->packet[12]) << 8 | p->packet[13])); |
|
|
DBGPRINTLN(String((uint32_t) (((p->packet[10] << 8) | p->packet[11]) << 8 | p->packet[12]) << 8 | p->packet[13])); |
|
|
//DBGPRINTLN(String((p->packet[12] << 8) + p->packet[13]));
|
|
|
mPayload[iv->id].gotFragment = true; |
|
|
if ( p->packet[9] == 0x01 ) { |
|
|
|
|
|
iv->setValue(iv->getPosByChFld(0, FLD_YT, rec), rec, (float) ((p->packet[20] << 8) + p->packet[21])/1); |
|
|
iv->setValue(iv->getPosByChFld(0, FLD_YT, rec), rec, (float) ((p->packet[20] << 8) + p->packet[21])/1); |
|
|
if(mSerialDebug) { |
|
|
if(mSerialDebug) { |
|
|
DPRINT(DBG_INFO,F("HW_ECapValue ")); |
|
|
|
|
|
DBGPRINTLN(String((p->packet[20] << 8) + p->packet[21])); |
|
|
|
|
|
|
|
|
|
|
|
DPRINT(DBG_INFO,F("HW_FB_TLmValue ")); |
|
|
DPRINT(DBG_INFO,F("HW_FB_TLmValue ")); |
|
|
DBGPRINTLN(String((p->packet[14] << 8) + p->packet[15])); |
|
|
DBGPRINTLN(String((p->packet[14] << 8) + p->packet[15])); |
|
|
DPRINT(DBG_INFO,F("HW_FB_ReSPRT ")); |
|
|
DPRINT(DBG_INFO,F("HW_FB_ReSPRT ")); |
|
|
DBGPRINTLN(String((p->packet[16] << 8) + p->packet[17])); |
|
|
DBGPRINTLN(String((p->packet[16] << 8) + p->packet[17])); |
|
|
DPRINT(DBG_INFO,F("HW_GridSamp_ResValule ")); |
|
|
DPRINT(DBG_INFO,F("HW_GridSamp_ResValule ")); |
|
|
DBGPRINTLN(String((p->packet[18] << 8) + p->packet[19])); |
|
|
DBGPRINTLN(String((p->packet[18] << 8) + p->packet[19])); |
|
|
|
|
|
DPRINT(DBG_INFO,F("HW_ECapValue ")); |
|
|
|
|
|
DBGPRINTLN(String((p->packet[20] << 8) + p->packet[21])); |
|
|
} |
|
|
} |
|
|
|
|
|
} else { |
|
|
|
|
|
DBGPRINTLN(F("3rd gen. inverter!")); // see table in OpenDTU code, DevInfoParser.cpp devInfo[]
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
} else if ( p->packet[9] == 0x12 ) {//3rd frame
|
|
|
} else if ( p->packet[9] == 0x12 ) {//3rd frame
|
|
|
DPRINT_IVID(DBG_INFO, iv->id); |
|
|
DPRINT_IVID(DBG_INFO, iv->id); |
|
|
DBGPRINTLN(F("got 3rd frame (hw info)")); |
|
|
DBGPRINTLN(F("got 3rd frame (hw info)")); |
|
|
iv->setQueuedCmdFinished(); |
|
|
iv->setQueuedCmdFinished(); |
|
|
|
|
|
mPayload[iv->id].complete = true; |
|
|
mStat->rxSuccess++; |
|
|
mStat->rxSuccess++; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -347,7 +345,9 @@ const byteAssign_t InfoAssignment[] = { |
|
|
payloadLen -= 2; |
|
|
payloadLen -= 2; |
|
|
|
|
|
|
|
|
if (mSerialDebug) { |
|
|
if (mSerialDebug) { |
|
|
DPRINT(DBG_INFO, F("Payload (") + String(payloadLen) + "): "); |
|
|
DPRINT(DBG_INFO, F("Payload (")); |
|
|
|
|
|
DBGPRINT(String(payloadLen)); |
|
|
|
|
|
DBGPRINT("): "); |
|
|
mSys->Radio.dumpBuf(payload, payloadLen); |
|
|
mSys->Radio.dumpBuf(payload, payloadLen); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -448,8 +448,8 @@ const byteAssign_t InfoAssignment[] = { |
|
|
} else { |
|
|
} else { |
|
|
bool change = false; |
|
|
bool change = false; |
|
|
if ( cmd >= 0x36 && cmd < 0x39 ) { // MI-1500 Data command
|
|
|
if ( cmd >= 0x36 && cmd < 0x39 ) { // MI-1500 Data command
|
|
|
//cmd++; // just request the next channel
|
|
|
if (cmd > 0x36 && mPayload[iv->id].retransmits==1) // first request for the upper channels
|
|
|
//change = true;
|
|
|
change = true; |
|
|
} else if ( cmd == 0x09 ) {//MI single or dual channel device
|
|
|
} else if ( cmd == 0x09 ) {//MI single or dual channel device
|
|
|
if ( mPayload[iv->id].dataAB[CH1] && iv->type == INV_TYPE_2CH ) { |
|
|
if ( mPayload[iv->id].dataAB[CH1] && iv->type == INV_TYPE_2CH ) { |
|
|
if (!mPayload[iv->id].stsAB[CH1] && mPayload[iv->id].retransmits<2) {} |
|
|
if (!mPayload[iv->id].stsAB[CH1] && mPayload[iv->id].retransmits<2) {} |
|
@ -641,7 +641,6 @@ const byteAssign_t InfoAssignment[] = { |
|
|
( p->packet[0] == 0x91 || p->packet[0] == (0x37 + ALL_FRAMES) ) ? CH2 : |
|
|
( p->packet[0] == 0x91 || p->packet[0] == (0x37 + ALL_FRAMES) ) ? CH2 : |
|
|
p->packet[0] == (0x38 + ALL_FRAMES) ? CH3 : |
|
|
p->packet[0] == (0x38 + ALL_FRAMES) ? CH3 : |
|
|
CH4; |
|
|
CH4; |
|
|
//DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") data msg 0x") + String(p->packet[0], HEX) + F(" channel ") + datachan);
|
|
|
|
|
|
// count in RF_communication_protocol.xlsx is with offset = -1
|
|
|
// count in RF_communication_protocol.xlsx is with offset = -1
|
|
|
iv->setValue(iv->getPosByChFld(datachan, FLD_UDC, rec), rec, (float)((p->packet[9] << 8) + p->packet[10])/10); |
|
|
iv->setValue(iv->getPosByChFld(datachan, FLD_UDC, rec), rec, (float)((p->packet[9] << 8) + p->packet[10])/10); |
|
|
yield(); |
|
|
yield(); |
|
@ -656,7 +655,6 @@ const byteAssign_t InfoAssignment[] = { |
|
|
yield(); |
|
|
yield(); |
|
|
iv->setValue(iv->getPosByChFld(0, FLD_T, rec), rec, (float) ((int16_t)(p->packet[21] << 8) + p->packet[22])/10); |
|
|
iv->setValue(iv->getPosByChFld(0, FLD_T, rec), rec, (float) ((int16_t)(p->packet[21] << 8) + p->packet[22])/10); |
|
|
iv->setValue(iv->getPosByChFld(0, FLD_IRR, rec), rec, (float) (calcIrradiation(iv, datachan))); |
|
|
iv->setValue(iv->getPosByChFld(0, FLD_IRR, rec), rec, (float) (calcIrradiation(iv, datachan))); |
|
|
//AC Power is missing; we may have to calculate, as no respective data is in payload
|
|
|
|
|
|
|
|
|
|
|
|
if ( datachan < 3 ) { |
|
|
if ( datachan < 3 ) { |
|
|
mPayload[iv->id].dataAB[datachan] = true; |
|
|
mPayload[iv->id].dataAB[datachan] = true; |
|
@ -687,17 +685,13 @@ const byteAssign_t InfoAssignment[] = { |
|
|
mSys->Radio.prepareDevInformCmd(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex, false, cmd); |
|
|
mSys->Radio.prepareDevInformCmd(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex, false, cmd); |
|
|
mPayload[iv->id].txCmd = cmd;*/ |
|
|
mPayload[iv->id].txCmd = cmd;*/ |
|
|
mPayload[iv->id].txCmd++; |
|
|
mPayload[iv->id].txCmd++; |
|
|
if (mPayload[iv->id].retransmits) |
|
|
mPayload[iv->id].retransmits = 0; // reserve retransmissions for each response
|
|
|
mPayload[iv->id].retransmits--; // reserve retransmissions for each response
|
|
|
|
|
|
mPayload[iv->id].complete = false; |
|
|
mPayload[iv->id].complete = false; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
else if (p->packet[0] == (0x39 + ALL_FRAMES) ) { |
|
|
/*else if ( p->packet[0] == (0x39 + ALL_FRAMES) ) {
|
|
|
/*uint8_t cmd = p->packet[0] - ALL_FRAMES + 1;
|
|
|
|
|
|
mSys->Radio.prepareDevInformCmd(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex, false, cmd); |
|
|
|
|
|
mPayload[iv->id].txCmd = cmd;*/ |
|
|
|
|
|
mPayload[iv->id].complete = true; |
|
|
mPayload[iv->id].complete = true; |
|
|
} |
|
|
}*/ |
|
|
|
|
|
|
|
|
/*if (iv->alarmMesIndex < rec->record[iv->getPosByChFld(0, FLD_EVT, rec)]){
|
|
|
/*if (iv->alarmMesIndex < rec->record[iv->getPosByChFld(0, FLD_EVT, rec)]){
|
|
|
iv->alarmMesIndex = rec->record[iv->getPosByChFld(0, FLD_EVT, rec)]; |
|
|
iv->alarmMesIndex = rec->record[iv->getPosByChFld(0, FLD_EVT, rec)]; |
|
@ -709,16 +703,7 @@ const byteAssign_t InfoAssignment[] = { |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if ( mPayload[iv->id].complete || //4ch device
|
|
|
/*
|
|
|
(iv->type != INV_TYPE_4CH //other devices
|
|
|
|
|
|
&& mPayload[iv->id].dataAB[CH0] |
|
|
|
|
|
&& mPayload[iv->id].stsAB[CH0])) { |
|
|
|
|
|
miComplete(iv); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
if(AlarmData == mPayload[iv->id].txCmd) { |
|
|
if(AlarmData == mPayload[iv->id].txCmd) { |
|
|
uint8_t i = 0; |
|
|
uint8_t i = 0; |
|
|
uint16_t code; |
|
|
uint16_t code; |
|
@ -732,12 +717,20 @@ const byteAssign_t InfoAssignment[] = { |
|
|
yield(); |
|
|
yield(); |
|
|
} |
|
|
} |
|
|
}*/ |
|
|
}*/ |
|
|
|
|
|
|
|
|
|
|
|
//if ( mPayload[iv->id].complete || //4ch device
|
|
|
|
|
|
if ( p->packet[0] == (0x39 + ALL_FRAMES) || //4ch device - last message
|
|
|
|
|
|
(iv->type != INV_TYPE_4CH //other devices
|
|
|
|
|
|
&& mPayload[iv->id].dataAB[CH0] |
|
|
|
|
|
&& mPayload[iv->id].stsAB[CH0])) { |
|
|
|
|
|
miComplete(iv); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void miComplete(Inverter<> *iv) { |
|
|
void miComplete(Inverter<> *iv) { |
|
|
if (mPayload[iv->id].complete) |
|
|
if ( mPayload[iv->id].complete ) // && iv->type != INV_TYPE_4CH)
|
|
|
return; //if we got second message as well in repreated attempt
|
|
|
return; // if we got second message as well in repreated attempt
|
|
|
mPayload[iv->id].complete = true; // For 2 CH devices, this might be too short...
|
|
|
mPayload[iv->id].complete = true; |
|
|
DPRINT_IVID(DBG_INFO, iv->id); |
|
|
DPRINT_IVID(DBG_INFO, iv->id); |
|
|
DBGPRINTLN(F("got all msgs")); |
|
|
DBGPRINTLN(F("got all msgs")); |
|
|
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); |
|
|
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); |
|
@ -778,6 +771,27 @@ const byteAssign_t InfoAssignment[] = { |
|
|
return true; |
|
|
return true; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* uint16_t mParseAlarmLog(uint8_t id, uint8_t pyld[], uint8_t len, uint32_t *start, uint32_t *endTime) {
|
|
|
|
|
|
uint8_t startOff = 2 + id * ALARM_LOG_ENTRY_SIZE; |
|
|
|
|
|
if((startOff + ALARM_LOG_ENTRY_SIZE) > len) |
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
|
|
|
|
uint16_t wCode = ((uint16_t)pyld[startOff]) << 8 | pyld[startOff+1]; |
|
|
|
|
|
uint32_t startTimeOffset = 0, endTimeOffset = 0; |
|
|
|
|
|
|
|
|
|
|
|
if (((wCode >> 13) & 0x01) == 1) // check if is AM or PM
|
|
|
|
|
|
startTimeOffset = 12 * 60 * 60; |
|
|
|
|
|
if (((wCode >> 12) & 0x01) == 1) // check if is AM or PM
|
|
|
|
|
|
endTimeOffset = 12 * 60 * 60; |
|
|
|
|
|
|
|
|
|
|
|
*start = (((uint16_t)pyld[startOff + 4] << 8) | ((uint16_t)pyld[startOff + 5])) + startTimeOffset; |
|
|
|
|
|
*endTime = (((uint16_t)pyld[startOff + 6] << 8) | ((uint16_t)pyld[startOff + 7])) + endTimeOffset; |
|
|
|
|
|
|
|
|
|
|
|
DPRINTLN(DBG_INFO, "Alarm #" + String(pyld[startOff+1]) + " '" + String(getAlarmStr(pyld[startOff+1])) + "' start: " + ah::getTimeStr(*start) + ", end: " + ah::getTimeStr(*endTime)); |
|
|
|
|
|
return pyld[startOff+1]; |
|
|
|
|
|
} |
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
void reset(uint8_t id, bool clrSts = false) { |
|
|
void reset(uint8_t id, bool clrSts = false) { |
|
|
DPRINT_IVID(DBG_INFO, id); |
|
|
DPRINT_IVID(DBG_INFO, id); |
|
|
DBGPRINTLN(F("resetPayload")); |
|
|
DBGPRINTLN(F("resetPayload")); |
|
|