Browse Source

Merge branch 'rejoe2-development03' into development03

pull/753/head
lumapu 2 years ago
parent
commit
fd698f2db8
  1. 17
      src/hm/hmInverter.h
  2. 438
      src/hm/miPayload.h

17
src/hm/hmInverter.h

@ -163,9 +163,26 @@ class Inverter {
uint8_t getQueuedCmd() { uint8_t getQueuedCmd() {
if (_commandQueue.empty()) { if (_commandQueue.empty()) {
if (ivGen != IV_MI) {
if (getFwVersion() == 0) if (getFwVersion() == 0)
enqueCommand<InfoCommand>(InverterDevInform_All); // firmware version enqueCommand<InfoCommand>(InverterDevInform_All); // firmware version
enqueCommand<InfoCommand>(RealTimeRunData_Debug); // live data enqueCommand<InfoCommand>(RealTimeRunData_Debug); // live data
} else if (ivGen == IV_MI){
if (type == INV_TYPE_4CH) {
enqueCommand<InfoCommand>(0x36);
/*for(uint8_t i = 0x36; i <= 0x39; i++) {
enqueCommand<MiInfoCommand>(i); // live data
}*/
} else if (type == INV_TYPE_2CH) {
enqueCommand<InfoCommand>(0x09);
//enqueCommand<MiInfoCommand>(0x11);
} else if (type == INV_TYPE_1CH) {
enqueCommand<InfoCommand>(0x09);
}
//if (getFwVersion() == 0)
// enqueCommand<MiInfoCommand>(InverterDevInform_All); // firmware version, might not work, esp. for 1/2 ch hardware
}
if ((actPowerLimit == 0xffff) && isConnected) if ((actPowerLimit == 0xffff) && isConnected)
enqueCommand<InfoCommand>(SystemConfigPara); // power limit info enqueCommand<InfoCommand>(SystemConfigPara); // power limit info
} }

438
src/hm/miPayload.h

@ -18,11 +18,13 @@ typedef struct {
uint8_t txCmd; uint8_t txCmd;
uint8_t len[MAX_PAYLOAD_ENTRIES]; uint8_t len[MAX_PAYLOAD_ENTRIES];
bool complete; bool complete;
bool stsa; bool dataAB[3];
bool stsb; bool stsAB[3];
uint8_t sts[5];
uint8_t txId; uint8_t txId;
uint8_t invId; uint8_t invId;
uint8_t retransmits; uint8_t retransmits;
bool gotFragment;
/* /*
uint8_t data[MAX_PAYLOAD_ENTRIES][MAX_RF_PAYLOAD_SIZE]; uint8_t data[MAX_PAYLOAD_ENTRIES][MAX_RF_PAYLOAD_SIZE];
@ -65,6 +67,7 @@ class MiPayload {
void addAlarmListener(alarmListenerType cb) { void addAlarmListener(alarmListenerType cb) {
mCbMiAlarm = cb; mCbMiAlarm = cb;
} }
void loop() { void loop() {
/*if(NULL != mHighPrioIv) { /*if(NULL != mHighPrioIv) {
iv->ivSend(mHighPrioIv, true); // should request firmware version etc.? iv->ivSend(mHighPrioIv, true); // should request firmware version etc.?
@ -84,62 +87,108 @@ class MiPayload {
if (mSerialDebug) if (mSerialDebug)
DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") Requesting Inv SN ") + String(iv->config->serial.u64, HEX)); DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") Requesting Inv SN ") + String(iv->config->serial.u64, HEX));
uint8_t cmd = iv->type == INV_TYPE_4CH ? 0x36 : 0x09; //iv->getQueuedCmd(); uint8_t cmd = iv->getQueuedCmd();
DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") prepareDevInformCmd")); DPRINT(DBG_INFO, F("(#"));
mSys->Radio.prepareDevInformCmd(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex, false, cmd); DBGPRINT(String(iv->id));
DBGPRINT(F(") prepareDevInformCmd 0x"));
DBGPRINTLN(String(cmd, HEX));
uint8_t cmd2 = cmd;
if (cmd == 0x1 ) {
cmd = TX_REQ_INFO;
cmd2 = 0x00;
};
mSys->Radio.prepareDevInformCmd(iv->radioId.u64, cmd2, mPayload[iv->id].ts, iv->alarmMesIndex, false, cmd);
mPayload[iv->id].txCmd = cmd; mPayload[iv->id].txCmd = cmd;
if (iv->type == INV_TYPE_1CH || iv->type == INV_TYPE_2CH) {
mPayload[iv->id].dataAB[CH1] = false;
mPayload[iv->id].stsAB[CH1] = false;
mPayload[iv->id].dataAB[CH0] = false;
mPayload[iv->id].stsAB[CH0] = false;
}
if (iv->type == INV_TYPE_2CH) {
mPayload[iv->id].dataAB[CH2] = false;
mPayload[iv->id].stsAB[CH2] = false;
}
} }
void add(Inverter<> *iv, packet_t *p) { void add(Inverter<> *iv, packet_t *p) {
//DPRINTLN(DBG_INFO, F("MI got data [0]=") + String(p->packet[0], HEX)); //DPRINTLN(DBG_INFO, F("MI got data [0]=") + String(p->packet[0], HEX));
if (p->packet[0] == (0x08 + ALL_FRAMES)) { // 0x88; MI status response to 0x09 if (p->packet[0] == (0x08 + ALL_FRAMES)) { // 0x88; MI status response to 0x09
mPayload[iv->id].stsa = true;
miStsDecode(iv, p); miStsDecode(iv, p);
} else if (p->packet[0] == (0x11 + SINGLE_FRAME)) { // 0x92; MI status response to 0x11 } else if (p->packet[0] == (0x11 + SINGLE_FRAME)) { // 0x92; MI status response to 0x11
mPayload[iv->id].stsb = true;
miStsDecode(iv, p, CH2); miStsDecode(iv, p, CH2);
} else if (p->packet[0] == (0x09 + ALL_FRAMES)) { // MI data response to 0x09 /*} else if (p->packet[0] == (0x09 + ALL_FRAMES)) { // MI data response to 0x09
mPayload[iv->id].txId = p->packet[0]; mPayload[iv->id].txId = p->packet[0];
miDataDecode(iv,p); miDataDecode(iv,p);
iv->setQueuedCmdFinished(); //iv->setQueuedCmdFinished();
if (INV_TYPE_2CH == iv->type) { if (INV_TYPE_2CH == iv->type) {
//mSys->Radio.prepareDevInformCmd(iv->radioId.u64, iv->getQueuedCmd(), mPayload[iv->id].ts, iv->alarmMesIndex, false, 0x11); //mSys->Radio.prepareDevInformCmd(iv->radioId.u64, iv->getQueuedCmd(), mPayload[iv->id].ts, iv->alarmMesIndex, false, 0x11);
mSys->Radio.prepareDevInformCmd(iv->radioId.u64, 0x11, mPayload[iv->id].ts, iv->alarmMesIndex, false, 0x11); //mSys->Radio.prepareDevInformCmd(iv->radioId.u64, 0x11, mPayload[iv->id].ts, iv->alarmMesIndex, false, 0x11);
} else { // additional check for mPayload[iv->id].stsa == true might be a good idea (request retransmit?) } else { // additional check for mPayload[iv->id].stsa == true might be a good idea (request retransmit?)
mPayload[iv->id].complete = true; mPayload[iv->id].complete = true;
//iv->setQueuedCmdFinished(); //iv->setQueuedCmdFinished();
} }
} else if (p->packet[0] == (0x11 + ALL_FRAMES)) { // MI data response to 0x11 } else if (p->packet[0] == ()) { // MI data response to 0x11
mPayload[iv->id].txId = p->packet[0]; mPayload[iv->id].txId = p->packet[0];
mPayload[iv->id].complete = true;
miDataDecode(iv,p); miDataDecode(iv,p);
iv->setQueuedCmdFinished(); mStat->rxSuccess++;
//iv->setQueuedCmdFinished();*/
} else if (p->packet[0] >= (0x36 + ALL_FRAMES) && p->packet[0] < (0x39 + SINGLE_FRAME)) { // MI 1500 data response to 0x36, 0x37, 0x38 and 0x39 } else if ( p->packet[0] == 0x09 + ALL_FRAMES ||
p->packet[0] == 0x11 + ALL_FRAMES ||
( p->packet[0] >= (0x36 + ALL_FRAMES) && p->packet[0] < (0x39 + SINGLE_FRAME) ) ) { // small MI or MI 1500 data responses to 0x09, 0x11, 0x36, 0x37, 0x38 and 0x39
mPayload[iv->id].txId = p->packet[0]; mPayload[iv->id].txId = p->packet[0];
miDataDecode(iv,p); miDataDecode(iv,p);
iv->setQueuedCmdFinished(); //mStat->rxSuccess++;
if (p->packet[0] < (0x39 + ALL_FRAMES)) { //iv->setQueuedCmdFinished();
/*if (p->packet[0] < (0x39 + ALL_FRAMES)) {
//mSys->Radio.prepareDevInformCmd(iv->radioId.u64, iv->getQueuedCmd(), mPayload[iv->id].ts, iv->alarmMesIndex, false, p->packet[0] + 1 - ALL_FRAMES); //mSys->Radio.prepareDevInformCmd(iv->radioId.u64, iv->getQueuedCmd(), mPayload[iv->id].ts, iv->alarmMesIndex, false, p->packet[0] + 1 - ALL_FRAMES);
mSys->Radio.prepareDevInformCmd(iv->radioId.u64, p->packet[0] + 1 - ALL_FRAMES, mPayload[iv->id].ts, iv->alarmMesIndex, false, p->packet[0] + 1 - ALL_FRAMES); //mSys->Radio.prepareDevInformCmd(iv->radioId.u64, p->packet[0] + 1 - ALL_FRAMES, mPayload[iv->id].ts, iv->alarmMesIndex, false, p->packet[0] + 1 - ALL_FRAMES);
} else { } else {
mPayload[iv->id].complete = true; mPayload[iv->id].complete = true;
//iv->setValue(iv->getPosByChFld(0, FLD_YD, rec), rec, CALC_YD_CH0); //iv->setValue(iv->getPosByChFld(0, FLD_YD, rec), rec, CALC_YD_CH0);
//iv->setQueuedCmdFinished(); //iv->setQueuedCmdFinished();
} }*/
/*} //}
} else if (p->packet[0] == (TX_REQ_INFO + ALL_FRAMES)) { // response from get information command
// atm, we just do nothing else than print out what we got...
// for decoding see xls- Data collection instructions - #147ff
/*
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
if (p->packet[0] == (TX_REQ_INFO + ALL_FRAMES)) { // response from get information command */
mPayload[iv->id].txId = p->packet[0]; mPayload[iv->id].txId = p->packet[0];
DPRINTLN(DBG_DEBUG, F("Response from info request received")); DPRINTLN(DBG_DEBUG, F("Response from info request received"));
uint8_t *pid = &p->packet[9]; uint8_t *pid = &p->packet[9];
if (*pid == 0x00) { if (*pid == 0x00) {
DPRINT(DBG_DEBUG, F("fragment number zero received and ignored")); DPRINT(DBG_DEBUG, F("fragment number zero received"));
} else {
iv->setQueuedCmdFinished();
} //else {
DPRINTLN(DBG_DEBUG, "PID: 0x" + String(*pid, HEX)); DPRINTLN(DBG_DEBUG, "PID: 0x" + String(*pid, HEX));
/*
if ((*pid & 0x7F) < MAX_PAYLOAD_ENTRIES) { if ((*pid & 0x7F) < MAX_PAYLOAD_ENTRIES) {
memcpy(mPayload[iv->id].data[(*pid & 0x7F) - 1], &p->packet[10], p->len - 11); memcpy(mPayload[iv->id].data[(*pid & 0x7F) - 1], &p->packet[10], p->len - 11);
mPayload[iv->id].len[(*pid & 0x7F) - 1] = p->len - 11; mPayload[iv->id].len[(*pid & 0x7F) - 1] = p->len - 11;
@ -242,13 +291,21 @@ class MiPayload {
if (IV_HM == iv->ivGen) // only process MI inverters if (IV_HM == iv->ivGen) // only process MI inverters
continue; // skip to next inverter continue; // skip to next inverter
/*if ((mPayload[iv->id].txId != (TX_REQ_INFO + ALL_FRAMES)) && (0 != mPayload[iv->id].txId)) { if ((mPayload[iv->id].txId != (TX_REQ_INFO + ALL_FRAMES)) &&
// no processing needed if txId is not 0x95 (mPayload[iv->id].txId < (0x36 + ALL_FRAMES)) &&
(mPayload[iv->id].txId > (0x39 + ALL_FRAMES)) &&
(mPayload[iv->id].txId != (0x09 + ALL_FRAMES)) &&
(mPayload[iv->id].txId != (0x11 + ALL_FRAMES)) &&
(mPayload[iv->id].txId != (0x88)) &&
(mPayload[iv->id].txId != (0x92)) &&
(mPayload[iv->id].txId != 0 )) {
// no processing needed if txId is not one of 0x95, 0x88, 0x89, 0x91, 0x92 or resonse to 0x36ff
mPayload[iv->id].complete = true; mPayload[iv->id].complete = true;
continue; // skip to next inverter continue; // skip to next inverter
}*/ }
if (!mPayload[iv->id].complete) { if (!mPayload[iv->id].complete) {
//DPRINTLN(DBG_INFO, F("Pyld incompl code")); //info for testing only
bool crcPass, pyldComplete; bool crcPass, pyldComplete;
crcPass = build(iv->id, &pyldComplete); crcPass = build(iv->id, &pyldComplete);
if (!crcPass && !pyldComplete) { // payload not complete if (!crcPass && !pyldComplete) { // payload not complete
@ -263,21 +320,32 @@ class MiPayload {
} else { } else {
if (mPayload[iv->id].retransmits < mMaxRetrans) { if (mPayload[iv->id].retransmits < mMaxRetrans) {
mPayload[iv->id].retransmits++; mPayload[iv->id].retransmits++;
//mSys->Radio.prepareDevInformCmd(iv->radioId.u64, iv->getQueuedCmd(), mPayload[iv->id].ts, iv->alarmMesIndex, false, 0x11); if( !mPayload[iv->id].gotFragment ) {
mSys->Radio.sendCmdPacket(iv->radioId.u64, iv->getQueuedCmd(), 24, true); DPRINT(DBG_INFO, F("(#"));
/*if(false == mPayload[iv->id].gotFragment) { DBGPRINT(String(iv->id));
DPRINTLN(DBG_WARN, F("(#") + String(iv->id) + F(") nothing received")); DBGPRINTLN(F(") nothing received"));
mPayload[iv->id].retransmits = mMaxRetrans; mPayload[iv->id].retransmits = mMaxRetrans;
} else { } else {
for (uint8_t i = 0; i < (mPayload[iv->id].maxPackId - 1); i++) { uint8_t cmd = mPayload[iv->id].txCmd;
if (mPayload[iv->id].len[i] == 0) { if ( cmd >= 0x36 && cmd < 0x39 ) { // MI-1500 Data command
DPRINTLN(DBG_WARN, F("Frame ") + String(i + 1) + F(" missing: Request Retransmit")); cmd++; // just request the next channel
mSys->Radio.sendCmdPacket(iv->radioId.u64, TX_REQ_INFO, (SINGLE_FRAME + i), true); } else if ( cmd == 0x09 ) {//MI single or dual channel device
break; // only request retransmit one frame per loop if ( mPayload[iv->id].dataAB[CH1] && iv->type == INV_TYPE_2CH ) {
} if (!mPayload[iv->id].stsAB[CH2] || !mPayload[iv->id].dataAB[CH2] )
cmd = 0x11;
}
} else if ( cmd == 0x11) {
if ( mPayload[iv->id].dataAB[CH2] ) { // data is there, but no status
if (!mPayload[iv->id].stsAB[CH1] || !mPayload[iv->id].dataAB[CH1] )
cmd = 0x09;
}
}
DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") next request is 0x") + String(cmd, HEX));
//mSys->Radio.sendCmdPacket(iv->radioId.u64, cmd, cmd, true);
mSys->Radio.prepareDevInformCmd(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex, true, cmd);
mPayload[iv->id].txCmd = cmd;
yield(); yield();
} }
}*/
} }
} }
} }
@ -289,14 +357,25 @@ class MiPayload {
DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") prepareDevInformCmd 0x") + String(mPayload[iv->id].txCmd, HEX)); DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") prepareDevInformCmd 0x") + String(mPayload[iv->id].txCmd, HEX));
mSys->Radio.prepareDevInformCmd(iv->radioId.u64, mPayload[iv->id].txCmd, mPayload[iv->id].ts, iv->alarmMesIndex, true); mSys->Radio.prepareDevInformCmd(iv->radioId.u64, mPayload[iv->id].txCmd, mPayload[iv->id].ts, iv->alarmMesIndex, true);
} }
} /*else { // payload complete } else { // payload complete
DPRINTLN(DBG_INFO, F("procPyld: cmd: 0x") + String(mPayload[iv->id].txCmd, HEX)); DPRINTLN(DBG_INFO, F("procPyld: cmd: 0x") + String(mPayload[iv->id].txCmd, HEX));
DPRINTLN(DBG_INFO, F("procPyld: txid: 0x") + String(mPayload[iv->id].txId, HEX)); DPRINTLN(DBG_INFO, F("procPyld: txid: 0x") + String(mPayload[iv->id].txId, HEX));
DPRINTLN(DBG_DEBUG, F("procPyld: max: ") + String(mPayload[iv->id].maxPackId)); //DPRINTLN(DBG_DEBUG, F("procPyld: max: ") + String(mPayload[iv->id].maxPackId));
record_t<> *rec = iv->getRecordStruct(mPayload[iv->id].txCmd); // choose the parser //record_t<> *rec = iv->getRecordStruct(mPayload[iv->id].txCmd); // choose the parser
mPayload[iv->id].complete = true; mPayload[iv->id].complete = true;
uint8_t ac_pow = 0;
//if (mPayload[iv->id].sts[0] == 3) {
ac_pow = calcPowerDcCh0(iv, 0)*9.5;
//}
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); // choose the parser
iv->setValue(iv->getPosByChFld(0, FLD_PAC, rec), rec, (float) (ac_pow/10));
uint8_t payload[128]; DPRINTLN(DBG_INFO, F("proces: compl. set of msgs detected"));
iv->setValue(iv->getPosByChFld(0, FLD_YD, rec), rec, calcYieldDayCh0(iv,0));
iv->doCalculations();
/*uint8_t payload[128];
uint8_t payloadLen = 0; uint8_t payloadLen = 0;
memset(payload, 0, 128); memset(payload, 0, 128);
@ -345,8 +424,8 @@ class MiPayload {
mStat->rxFail++; mStat->rxFail++;
} }
iv->setQueuedCmdFinished(); iv->setQueuedCmdFinished(); */
}*/ }
} }
yield(); yield();
} }
@ -359,96 +438,159 @@ class MiPayload {
} }
void miStsDecode(Inverter<> *iv, packet_t *p, uint8_t chan = CH1) { void miStsDecode(Inverter<> *iv, packet_t *p, uint8_t chan = CH1) {
DPRINTLN(DBG_INFO, F("Inverter ") + String(iv->id) + F(": status msg 0x") + String(p->packet[0], HEX)); DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") status msg 0x") + String(p->packet[0], HEX));
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); // choose the record structure record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); // choose the record structure
rec->ts = mPayload[iv->id].ts; rec->ts = mPayload[iv->id].ts;
mPayload[iv->id].gotFragment = true;
mPayload[iv->id].txId = p->packet[0];
//iv->setValue(iv->getPosByChFld(chan, FLD_YD, rec), rec, (int)((p->packet[11+6] << 8) + p->packet[12+6])); // was 11/12, might be wrong! uint8_t status = (p->packet[11] << 8) + p->packet[12];
uint8_t stschan = p->packet[0] == 0x88 ? CH1 : CH2;
//if (INV_TYPE_1CH == iv->type) mPayload[iv->id].sts[stschan] = status;
//iv->setValue(iv->getPosByChFld(0, FLD_YD, rec), rec, (int)((p->packet[11+6] << 8) + p->packet[12+6])); mPayload[iv->id].stsAB[stschan] = true;
if (mPayload[iv->id].stsAB[CH1] && mPayload[iv->id].stsAB[CH2])
mPayload[iv->id].stsAB[CH0] = true;
if ( !mPayload[iv->id].sts[0] || status < mPayload[iv->id].sts[0]) {
mPayload[iv->id].sts[0] = status;
iv->setValue(iv->getPosByChFld(0, FLD_EVT, rec), rec, status);
}
//iv->setValue(iv->getPosByChFld(chan, FLD_EVT, rec), rec, (int)((p->packet[13] << 8) + p->packet[14])); /*if ( !mPayload[iv->id].dataAB[0] || !mPayload[iv->id].dataAB[1] ) {
uint8_t cmd = mPayload[iv->id].dataAB[0] ? 0x11 : 0x09;
DPRINTLN(DBG_INFO, F("request missing status 0x") + String(cmd, HEX));
mSys->Radio.prepareDevInformCmd(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex, false, cmd);
mPayload[iv->id].txCmd = cmd;
rem: gotFragment should be a better solution
} */
iv->setValue(iv->getPosByChFld(0, FLD_EVT, rec), rec, (int)((p->packet[11] << 8) + p->packet[12]));
//iv->setValue(iv->getPosByChFld(0, FLD_EVT, rec), rec, (int)((p->packet[14] << 8) + p->packet[16]));
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)]; // seems there's no status per channel in 3rd gen. models?!? iv->alarmMesIndex = rec->record[iv->getPosByChFld(0, FLD_EVT, rec)]; // seems there's no status per channel in 3rd gen. models?!?
DPRINTLN(DBG_INFO, "alarm ID incremented to " + String(iv->alarmMesIndex)); DPRINTLN(DBG_INFO, "alarm ID incremented to " + String(iv->alarmMesIndex));
iv->enqueCommand<InfoCommand>(AlarmData); iv->enqueCommand<InfoCommand>(AlarmData);
} }
/* Unclear how in HM inverters Info and alarm data is handled... if (mPayload[iv->id].stsAB[CH0] && mPayload[iv->id].dataAB[CH0] && !mPayload[iv->id].complete) {
*/ mPayload[iv->id].complete = true;
DPRINTLN(DBG_INFO, F("rec. complete set of msgs"));
iv->setValue(iv->getPosByChFld(0, FLD_YD, rec), rec, calcYieldDayCh0(iv,0));
/* int8_t offset = -2; iv->setQueuedCmdFinished();
iv->doCalculations();
for decoding see notify(mPayload[iv->id].txCmd);
void MI600StsMsg (NRF24_packet_t *p){
STAT = (int)((p->packet[11] << 8) + p->packet[12]);
FCNT = (int)((p->packet[13] << 8) + p->packet[14]);
FCODE = (int)((p->packet[15] << 8) + p->packet[16]);
#ifdef ESP8266
VALUES[PV][5]=STAT;
VALUES[PV][6]=FCNT;
VALUES[PV][7]=FCODE;
#endif
} }
*/
} }
void miDataDecode(Inverter<> *iv, packet_t *p) { void miDataDecode(Inverter<> *iv, packet_t *p) {
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); // choose the parser record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); // choose the parser
rec->ts = mPayload[iv->id].ts; rec->ts = mPayload[iv->id].ts;
mPayload[iv->id].gotFragment = true;
uint8_t datachan = ( p->packet[0] == 0x89 || p->packet[0] == (0x36 + ALL_FRAMES) ) ? CH1 : uint8_t datachan = ( p->packet[0] == 0x89 || p->packet[0] == (0x36 + ALL_FRAMES) ) ? CH1 :
( 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;
int8_t offset = -2; DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") data msg 0x") + String(p->packet[0], HEX) + F(" channel ") + datachan);
// U_DC = (float) ((p->packet[11] << 8) + p->packet[12])/10; // count in RF_communication_protocol.xlsx is with offset = -1
iv->setValue(iv->getPosByChFld(datachan, FLD_UDC, rec), rec, (float)((p->packet[11+offset] << 8) + p->packet[12+offset])/10); iv->setValue(iv->getPosByChFld(datachan, FLD_UDC, rec), rec, (float)((p->packet[9] << 8) + p->packet[10])/10);
yield(); yield();
// I_DC = (float) ((p->packet[13] << 8) + p->packet[14])/10; iv->setValue(iv->getPosByChFld(datachan, FLD_IDC, rec), rec, (float)((p->packet[11] << 8) + p->packet[12])/10);
iv->setValue(iv->getPosByChFld(datachan, FLD_IDC, rec), rec, (float)((p->packet[13+offset] << 8) + p->packet[14+offset])/10);
yield(); yield();
// U_AC = (float) ((p->packet[15] << 8) + p->packet[16])/10; iv->setValue(iv->getPosByChFld(0, FLD_UAC, rec), rec, (float)((p->packet[13] << 8) + p->packet[14])/10);
iv->setValue(iv->getPosByChFld(0, FLD_UAC, rec), rec, (float)((p->packet[15+offset] << 8) + p->packet[16+offset])/10);
yield(); yield();
// F_AC = (float) ((p->packet[17] << 8) + p->packet[18])/100; iv->setValue(iv->getPosByChFld(0, FLD_F, rec), rec, (float) ((p->packet[15] << 8) + p->packet[16])/100);
//iv->setValue(iv->getPosByChFld(0, FLD_IAC, rec), rec, (float)((p->packet[17+offset] << 8) + p->packet[18+offset])/100); iv->setValue(iv->getPosByChFld(datachan, FLD_PDC, rec), rec, (float)((p->packet[17] << 8) + p->packet[18])/10);
//yield();
// P_DC = (float)((p->packet[19] << 8) + p->packet[20])/10;
iv->setValue(iv->getPosByChFld(datachan, FLD_PDC, rec), rec, (float)((p->packet[19+offset] << 8) + p->packet[20+offset])/10);
yield(); yield();
// Q_DC = (float)((p->packet[21] << 8) + p->packet[22])/1; iv->setValue(iv->getPosByChFld(datachan, FLD_YD, rec), rec, (float)((p->packet[19] << 8) + p->packet[20])/1);
iv->setValue(iv->getPosByChFld(datachan, FLD_YD, rec), rec, (float)((p->packet[21+offset] << 8) + p->packet[22+offset])/1);
yield(); yield();
iv->setValue(iv->getPosByChFld(0, FLD_T, rec), rec, (float) ((int16_t)(p->packet[23+offset] << 8) + p->packet[24+offset])/10); //23 is freq or IAC? 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_F, rec), rec, (float) ((p->packet[17+offset] << 8) + p->packet[18+offset])/100);
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)));
yield(); //AC Power is missing; we may have to calculate, as no respective data is in payload
//FLD_YD
if ( datachan < 3 ) {
mPayload[iv->id].dataAB[datachan] = true;
}
if ( !mPayload[iv->id].dataAB[CH0] && mPayload[iv->id].dataAB[CH2] && mPayload[iv->id].dataAB[CH2] ) {
mPayload[iv->id].dataAB[CH0] = true;
}
if (p->packet[0] >= (0x36 + ALL_FRAMES) ) { if (p->packet[0] >= (0x36 + ALL_FRAMES) ) {
/*status message analysis most liklely needs to be changed, see MiStsMst*/
/*STAT = (uint8_t)(p->packet[25] ); /*For MI1500:
if (MI1500) {
STAT = (uint8_t)(p->packet[25] );
FCNT = (uint8_t)(p->packet[26]); FCNT = (uint8_t)(p->packet[26]);
FCODE = (uint8_t)(p->packet[27]); // MI300/Mi600 stsMsg:: (int)((p->packet[15] << 8) + p->packet[16]); */ FCODE = (uint8_t)(p->packet[27]);
iv->setValue(iv->getPosByChFld(0, FLD_EVT, rec), rec, (uint8_t)(p->packet[25+offset])); }*/
yield();
uint8_t status = (uint8_t)(p->packet[23]);
mPayload[iv->id].sts[datachan] = status;
if ( !mPayload[iv->id].sts[0] || status < mPayload[iv->id].sts[0]) {
mPayload[iv->id].sts[0] = status;
iv->setValue(iv->getPosByChFld(0, FLD_EVT, rec), rec, status);
}
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 = false;
}
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;
}
//iv->setValue(iv->getPosByChFld(0, FLD_EVT, rec), rec, calcMiSts(iv));yield();
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)];
DPRINTLN(DBG_INFO, "alarm ID incremented to " + String(iv->alarmMesIndex)); DPRINTLN(DBG_INFO, F("alarm ID incremented to ") + String(iv->alarmMesIndex));
iv->enqueCommand<InfoCommand>(AlarmData); //iv->enqueCommand<InfoCommand>(AlarmData);
} }
} }
//iv->setValue(iv->getPosByChFld(0, FLD_YD, rec), rec, CALC_YD_CH0); // (getValue(iv->getPosByChFld(1, FLD_YD, rec), rec) + getValue(iv->getPosByChFld(2, FLD_YD, rec), rec)));
iv->setValue(iv->getPosByChFld(0, FLD_YD, rec), rec, calcYieldDayCh0(iv,0)); //datachan)); //preliminary AC calculation...
uint8_t ac_pow = 0;
//if (mPayload[iv->id].sts[0] == 3) {
ac_pow = calcPowerDcCh0(iv, 0)*9.5;
//}
iv->setValue(iv->getPosByChFld(0, FLD_PAC, rec), rec, (float) (ac_pow/10));
if ( mPayload[iv->id].complete || //4ch device
iv->type != INV_TYPE_4CH //other devices
&& mPayload[iv->id].dataAB[CH0]
&& mPayload[iv->id].stsAB[CH0] ) {
mPayload[iv->id].complete = true; // For 2 CH devices, this might be too short...
DPRINTLN(DBG_INFO, F("rec. complete set of msgs"));
iv->setValue(iv->getPosByChFld(0, FLD_YD, rec), rec, calcYieldDayCh0(iv,0));
iv->doCalculations(); iv->doCalculations();
/*} else {
//retry to get missing status info for one or two channel devices
DPRINTLN(DBG_INFO, F("request missing data or status 0x") + String(cmd, HEX));
mSys->Radio.prepareDevInformCmd(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex, false, cmd);
mPayload[iv->id].txCmd = cmd;
//iv->enqueCommand(cmd); // mPayload[iv->id].dataAB[1] ? 0x09 : 0x11)
}*/
}
/* should be included in process()
else if (mPayload[iv->id].txCmd == 0x09 && iv->type == INV_TYPE_2CH) {
uint8_t cmd = 0x11;
DPRINTLN(DBG_INFO, F("request second data channel 0x") + String(cmd, HEX));
mSys->Radio.prepareDevInformCmd(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex, false, cmd);
mPayload[iv->id].txCmd = cmd;
mPayload[iv->id].complete = false;
}*/
iv->setQueuedCmdFinished();
mStat->rxSuccess++;
yield();
notify(mPayload[iv->id].txCmd); notify(mPayload[iv->id].txCmd);
/* /*
if(AlarmData == mPayload[iv->id].txCmd) { if(AlarmData == mPayload[iv->id].txCmd) {
uint8_t i = 0; uint8_t i = 0;
@ -463,66 +605,26 @@ class MiPayload {
yield(); yield();
} }
}*/ }*/
/*decode here or memcopy payload for later decoding?
void MI600DataMsg(NRF24_packet_t *p){
U_DC = (float) ((p->packet[11] << 8) + p->packet[12])/10;
I_DC = (float) ((p->packet[13] << 8) + p->packet[14])/10;
U_AC = (float) ((p->packet[15] << 8) + p->packet[16])/10;
F_AC = (float) ((p->packet[17] << 8) + p->packet[18])/100;
P_DC = (float)((p->packet[19] << 8) + p->packet[20])/10;
Q_DC = (float)((p->packet[21] << 8) + p->packet[22])/1;
TEMP = (float) ((p->packet[23] << 8) + p->packet[24])/10; //(int16_t)
if ((30<U_DC<50) && (0<I_DC<15) && (200<U_AC<300) && (45<F_AC<55) && (0<P_DC<420) && (0<TEMP<80))
DataOK = 1; //we need to check this, if no crc
else { DEBUG_OUT.printf("Data Wrong!!\r\n");DataOK =0; return;}
if (p->packet[2] == 0x89) {PV= 0; TotalP[1]=P_DC; pvCnt[0]=1;}//port 1
if (p->packet[2] == 0x91) {PV= 1; TotalP[2]=P_DC; pvCnt[1]=1;}//port 2
TotalP[0]=TotalP[1]+TotalP[2]+TotalP[3]+TotalP[4];//in TotalP[0] is the totalPV power
if((P_DC>400) || (P_DC<0) || (TotalP[0]>MAXPOWER)){// cant be!!
TotalP[0]=0;
return;
}
#ifdef ESP8266
VALUES[PV][0]=PV;
VALUES[PV][1]=P_DC;
VALUES[PV][2]=U_DC;
VALUES[PV][3]=I_DC;
VALUES[PV][4]=Q_DC;
#endif
PMI=TotalP[0];
LIM=(uint16_t)Limit;
PrintOutValues();
}*/
/*For MI1500:
if (MI1500) {
STAT = (uint8_t)(p->packet[25] );
FCNT = (uint8_t)(p->packet[26]);
FCODE = (uint8_t)(p->packet[27]);
}
*/
DPRINTLN(DBG_INFO, F("Inverter ") + String(iv->id) + F(": data msg 0x") + String(p->packet[0], HEX) + F(" channel ") + datachan);
} }
bool build(uint8_t id, bool *complete) { bool build(uint8_t id, bool *complete) {
/*DPRINTLN(DBG_VERBOSE, F("build")); DPRINTLN(DBG_VERBOSE, F("build"));
uint16_t crc = 0xffff, crcRcv = 0x0000; /*uint16_t crc = 0xffff, crcRcv = 0x0000;
if (mPayload[id].maxPackId > MAX_PAYLOAD_ENTRIES) if (mPayload[id].maxPackId > MAX_PAYLOAD_ENTRIES)
mPayload[id].maxPackId = MAX_PAYLOAD_ENTRIES; mPayload[id].maxPackId = MAX_PAYLOAD_ENTRIES;
*/
// check if all fragments are there // check if all messages are there
*complete = true;
for (uint8_t i = 0; i < mPayload[id].maxPackId; i++) { *complete = mPayload[id].complete;
if(mPayload[id].len[i] == 0) uint8_t txCmd = mPayload[id].txCmd;
*complete = false; //uint8_t cmd = getQueuedCmd();
} if(!*complete) {
if(!*complete) DPRINTLN(DBG_VERBOSE, F("incomlete, txCmd is 0x") + String(txCmd, HEX)); // + F("cmd is 0x") + String(cmd, HEX));
if (txCmd == 0x09 || txCmd == 0x11 || txCmd >= 0x36 && txCmd <= 0x39 )
return false; return false;
}
for (uint8_t i = 0; i < mPayload[id].maxPackId; i++) { /*for (uint8_t i = 0; i < mPayload[id].maxPackId; i++) {
if (mPayload[id].len[i] > 0) { if (mPayload[id].len[i] > 0) {
if (i == (mPayload[id].maxPackId - 1)) { if (i == (mPayload[id].maxPackId - 1)) {
crc = ah::crc16(mPayload[id].data[i], mPayload[id].len[i] - 2, crc); crc = ah::crc16(mPayload[id].data[i], mPayload[id].len[i] - 2, crc);
@ -538,21 +640,53 @@ class MiPayload {
} }
void reset(uint8_t id) { void reset(uint8_t id) {
DPRINTLN(DBG_INFO, "resetPayload: id: " + String(id)); DPRINTLN(DBG_INFO, F("resetPayload: id: ") + String(id));
memset(mPayload[id].len, 0, MAX_PAYLOAD_ENTRIES); memset(mPayload[id].len, 0, MAX_PAYLOAD_ENTRIES);
/*
mPayload[id].gotFragment = false; mPayload[id].gotFragment = false;
mPayload[id].maxPackId = MAX_PAYLOAD_ENTRIES; /*mPayload[id].maxPackId = MAX_PAYLOAD_ENTRIES;
mPayload[id].lastFound = false;*/ mPayload[id].lastFound = false;*/
mPayload[id].retransmits = 0; mPayload[id].retransmits = 0;
mPayload[id].complete = false; mPayload[id].complete = false;
mPayload[id].dataAB[CH0] = true; //required for 1CH and 2CH devices
mPayload[id].dataAB[CH1] = true; //required for 1CH and 2CH devices
mPayload[id].dataAB[CH2] = true; //only required for 2CH devices
mPayload[id].stsAB[CH0] = true; //required for 1CH and 2CH devices
mPayload[id].stsAB[CH1] = true; //required for 1CH and 2CH devices
mPayload[id].stsAB[CH2] = true; //only required for 2CH devices
mPayload[id].txCmd = 0; mPayload[id].txCmd = 0;
mPayload[id].requested = false; mPayload[id].requested = false;
mPayload[id].ts = *mTimestamp; mPayload[id].ts = *mTimestamp;
mPayload[id].stsa = false; mPayload[id].sts[0] = 0; //disable this in case gotFragment is not working
mPayload[id].stsb = false; mPayload[id].sts[CH1] = 0;
mPayload[id].sts[CH2] = 0;
mPayload[id].sts[CH3] = 0;
mPayload[id].sts[CH4] = 0;
} }
/* template<class T=uint8_t>
static T calcMiSts(Inverter<> *iv) {
if(NULL != iv) {
T result = 0;
bool stsComplete = true;
uint8_t stsCh;
for(uint8_t i = 1; i <= iv->channels; i++) {
stsCh = mPayload[iv->id].sts[i];
if (!stsCh) {
stsComplete = false;
} else if ( !result || stsCh < result ) {
result = stsCh;
if (stsComplete && stsCh > stsComplete) {
stsComplete = stsCh;
}
}
}
mPayload[iv->id].sts[0] = stsComplete;
return result;
}
return 0;
} */
IApp *mApp; IApp *mApp;
HMSYSTEM *mSys; HMSYSTEM *mSys;
statistics_t *mStat; statistics_t *mStat;

Loading…
Cancel
Save