diff --git a/src/hm/Communication.h b/src/hm/Communication.h index 81dc763c..1336e78c 100644 --- a/src/hm/Communication.h +++ b/src/hm/Communication.h @@ -71,7 +71,8 @@ class Communication : public CommQueue<> { case States::CHECK_FRAMES: { if(!q->iv->radio->get()) { // radio buffer empty cmdDone(); - DPRINT(DBG_INFO, F("request timeout: ")); + DPRINT_IVID(DBG_INFO, q->iv->id); + DBGPRINT(F("request timeout: ")); DBGPRINT(String(millis() - mWaitTimeout + 500)); DBGPRINTLN(F("ms")); @@ -90,11 +91,15 @@ class Communication : public CommQueue<> { DPRINT_IVID(DBG_INFO, q->iv->id); DBGPRINT(F("RX ")); + if(p->millis < 100) + DBGPRINT(F("0")); DBGPRINT(String(p->millis)); DBGPRINT(F("ms ")); DBGPRINT(String(p->len)); - if(IV_HM == q->iv->ivGen) { + if((IV_HM == q->iv->ivGen) || (IV_MI == q->iv->ivGen)) { DBGPRINT(F(" CH")); + if(3 == p->ch) + DBGPRINT(F("0")); DBGPRINT(String(p->ch)); } DBGPRINT(F(", ")); @@ -111,6 +116,8 @@ class Communication : public CommQueue<> { } else if (p->packet[0] == (TX_REQ_DEVCONTROL + ALL_FRAMES)) { // response from dev control command parseDevCtrl(p, q); cmdDone(true); // remove done request + } else if(IV_MI == q->iv->ivGen) { + parseMiFrame(p, q); } } else DPRINTLN(DBG_WARN, F("Inverter serial does not match")); @@ -227,6 +234,74 @@ class Communication : public CommQueue<> { f->rssi = p->rssi; } + inline void parseMiFrame(packet_t *p, const queue_s *q) { + if ((p->packet[0] == MI_REQ_CH1 + ALL_FRAMES) + || (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))) { + // 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); + + } + } + + inline void miDataDecode(packet_t *p, const queue_s *q) { + record_t<> *rec = q->iv->getRecordStruct(RealTimeRunData_Debug); // choose the parser + //rec->ts = mPayload[iv->id].ts; + //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 : + CH4; + // count in RF_communication_protocol.xlsx is with offset = -1 + q->iv->setValue(q->iv->getPosByChFld(datachan, FLD_UDC, rec), rec, (float)((p->packet[9] << 8) + p->packet[10])/10); + + q->iv->setValue(q->iv->getPosByChFld(datachan, FLD_IDC, rec), rec, (float)((p->packet[11] << 8) + p->packet[12])/10); + + q->iv->setValue(q->iv->getPosByChFld(0, FLD_UAC, rec), rec, (float)((p->packet[13] << 8) + p->packet[14])/10); + + q->iv->setValue(q->iv->getPosByChFld(0, FLD_F, rec), rec, (float) ((p->packet[15] << 8) + p->packet[16])/100); + q->iv->setValue(q->iv->getPosByChFld(datachan, FLD_PDC, rec), rec, (float)((p->packet[17] << 8) + p->packet[18])/10); + + q->iv->setValue(q->iv->getPosByChFld(datachan, FLD_YD, rec), rec, (float)((p->packet[19] << 8) + p->packet[20])/1); + + 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 < 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) { + STAT = (uint8_t)(p->packet[25] ); + FCNT = (uint8_t)(p->packet[26]); + FCODE = (uint8_t)(p->packet[27]); + }*/ + //miStsConsolidate(iv, 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; + } else { + //miComplete(iv); + } + } else if((p->packet[0] == (MI_REQ_CH1 + ALL_FRAMES)) && q->iv->type == INV_TYPE_2CH ) { + addImportant(q->iv, MI_REQ_CH2); + } + } + inline void parseDevCtrl(packet_t *p, const queue_s *q) { if((p->packet[12] != ActivePowerContr) || (p->packet[13] != 0x00)) return; diff --git a/src/hm/hmDefines.h b/src/hm/hmDefines.h index acd81541..c00f4940 100644 --- a/src/hm/hmDefines.h +++ b/src/hm/hmDefines.h @@ -346,4 +346,8 @@ const devInfo_t devInfo[] = { { 0x103331, 2250 } }; +#define MI_REQ_CH1 0x09 +#define MI_REQ_CH2 0x11 +#define MI_REQ_4CH 0x36 + #endif /*__HM_DEFINES_H__*/ diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h index 45b861a7..618cf5da 100644 --- a/src/hm/hmInverter.h +++ b/src/hm/hmInverter.h @@ -182,19 +182,35 @@ class Inverter { } void tickSend(std::function cb) { - if(mDevControlRequest) { - cb(devControlCmd, true); - mDevControlRequest = false; - } else if((alarmLastId != alarmMesIndex) && (alarmMesIndex != 0)) - cb(AlarmData, false); // get last alarms - else if(0 == getFwVersion()) - cb(InverterDevInform_All, false); // get firmware version - else if(0 == getHwVersion()) - cb(InverterDevInform_Simple, false); // get hardware version - else if(actPowerLimit == 0xffff) - cb(SystemConfigPara, false); // power limit info - else - cb(RealTimeRunData_Debug, false); // get live data + if (IV_MI != ivGen) { + if(mDevControlRequest) { + cb(devControlCmd, true); + mDevControlRequest = false; + } else if((alarmLastId != alarmMesIndex) && (alarmMesIndex != 0)) + cb(AlarmData, false); // get last alarms + else if(0 == getFwVersion()) + cb(InverterDevInform_All, false); // get firmware version + else if(0 == getHwVersion()) + cb(InverterDevInform_Simple, false); // get hardware version + else if(actPowerLimit == 0xffff) + cb(SystemConfigPara, false); // power limit info + else + cb(RealTimeRunData_Debug, false); // get live data + } else { + if(mDevControlRequest) { + cb(devControlCmd, true); + mDevControlRequest = false; + } else if(0 == getFwVersion()) + cb(MI_REQ_CH1, false); // get firmware version + //cb(InverterDevInform_All, false); // get firmware version + else { + record_t<> *rec = getRecordStruct(InverterDevInform_Simple); + if (getChannelFieldValue(CH0, FLD_PART_NUM, rec) == 0) + cb(InverterDevInform_All, false); // hard- and firmware version for missing HW part nr, delivered by frame 1 + else + cb(type == INV_TYPE_4CH ? MI_REQ_4CH : MI_REQ_CH1, false); + } + } } /*template diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h index 461fd08e..3d74222d 100644 --- a/src/hm/hmRadio.h +++ b/src/hm/hmRadio.h @@ -117,24 +117,24 @@ class HmRadio : public Radio { mNrf24.setChannel(mRfChLst[mRxChIdx]); mNrf24.startListening(); - uint32_t startMicros = micros(); + uint32_t startMicros = micros() + 5110; uint32_t loopMillis = millis() + 400; while (millis() < loopMillis) { - while (micros()-startMicros < 5110) { // listen (4088us or?) 5110us to each channel + while (micros() < startMicros) { // listen (4088us or?) 5110us to each channel if (mIrqRcvd) { mIrqRcvd = false; - if (getReceived()) { // everything received + + if (getReceived()) // everything received return; - } + } yield(); } // switch to next RX channel - startMicros = micros(); if(++mRxChIdx >= RF_CHANNELS) mRxChIdx = 0; mNrf24.setChannel(mRfChLst[mRxChIdx]); - yield(); + startMicros = micros() + 5000; } // not finished but time is over return; @@ -145,12 +145,13 @@ class HmRadio : public Radio { return mNrf24.isChipConnected(); } - void sendControlPacket(Inverter<> *iv, uint8_t cmd, uint16_t *data, bool isRetransmit, bool isNoMI = true, uint16_t powerMax = 0) { - DPRINT(DBG_INFO, F("sendControlPacket cmd: 0x")); + void sendControlPacket(Inverter<> *iv, uint8_t cmd, uint16_t *data, bool isRetransmit) { + DPRINT_IVID(DBG_INFO, iv->id); + DBGPRINT(F("sendControlPacket cmd: 0x")); DBGHEXLN(cmd); initPacket(iv->radioId.u64, TX_REQ_DEVCONTROL, SINGLE_FRAME); uint8_t cnt = 10; - if (isNoMI) { + if (IV_MI != iv->ivGen) { mTxBuf[cnt++] = cmd; // cmd -> 0 on, 1 off, 2 restart, 11 active power, 12 reactive power, 13 power factor mTxBuf[cnt++] = 0x00; if(cmd >= ActivePowerContr && cmd <= PFSet) { // ActivePowerContr, ReactivePowerContr, PFSet @@ -160,6 +161,7 @@ class HmRadio : public Radio { mTxBuf[cnt++] = ((data[1] ) ) & 0xff; // setting for persistens handling } } else { //MI 2nd gen. specific + uint16_t powerMax = ((iv->powerLimit[1] == RelativNonPersistent) ? 0 : iv->getMaxPower()); switch (cmd) { case Restart: case TurnOn: @@ -225,7 +227,7 @@ class HmRadio : public Radio { } cnt++; } - sendPacket(iv, cnt, isRetransmit, isNoMI); + sendPacket(iv, cnt, isRetransmit, (IV_MI != iv->ivGen)); } uint8_t getDataRate(void) { @@ -297,6 +299,10 @@ class HmRadio : public Radio { return iv->radioId.u64; } + uint8_t getIvGen(Inverter<> *iv) { + return iv->ivGen; + } + uint64_t DTU_RADIO_ID; uint8_t mRfChLst[RF_CHANNELS]; uint8_t mTxChIdx; diff --git a/src/hm/radio.h b/src/hm/radio.h index 2096f108..75db5436 100644 --- a/src/hm/radio.h +++ b/src/hm/radio.h @@ -21,7 +21,7 @@ class Inverter; // abstract radio interface class Radio { public: - virtual void sendControlPacket(Inverter<> *iv, uint8_t cmd, uint16_t *data, bool isRetransmit, bool isNoMI = true, uint16_t powerMax = 0) = 0; + virtual void sendControlPacket(Inverter<> *iv, uint8_t cmd, uint16_t *data, bool isRetransmit) = 0; virtual bool switchFrequency(Inverter<> *iv, uint32_t fromkHz, uint32_t tokHz) { return true; } virtual void loop(void) {}; @@ -43,6 +43,14 @@ class Radio { } void prepareDevInformCmd(Inverter<> *iv, uint8_t cmd, uint32_t ts, uint16_t alarmMesId, bool isRetransmit, uint8_t reqfld=TX_REQ_INFO) { // might not be necessary to add additional arg. + if(IV_MI == getIvGen(iv)) { + DPRINT_IVID(DBG_INFO, getIvId(iv)); + DBGPRINT(F("legacy cmd 0x")); + DBGHEXLN(cmd); + sendCmdPacket(iv, cmd, cmd, false, false); + return; + } + if(mSerialDebug) { DPRINT(DBG_DEBUG, F("prepareDevInformCmd 0x")); DPRINTLN(DBG_DEBUG,String(cmd, HEX)); @@ -63,6 +71,7 @@ class Radio { protected: virtual void sendPacket(Inverter<> *iv, uint8_t len, bool isRetransmit, bool appendCrc16=true) = 0; virtual uint64_t getIvId(Inverter<> *iv) = 0; + virtual uint8_t getIvGen(Inverter<> *iv) = 0; void initPacket(uint64_t ivId, uint8_t mid, uint8_t pid) { mTxBuf[0] = mid; diff --git a/src/hms/hmsRadio.h b/src/hms/hmsRadio.h index 24c3c7cd..097a3f03 100644 --- a/src/hms/hmsRadio.h +++ b/src/hms/hmsRadio.h @@ -44,7 +44,7 @@ class CmtRadio : public Radio { return mCmtAvail; } - void sendControlPacket(Inverter<> *iv, uint8_t cmd, uint16_t *data, bool isRetransmit, bool isNoMI = true, uint16_t powerMax = 0) { + void sendControlPacket(Inverter<> *iv, uint8_t cmd, uint16_t *data, bool isRetransmit) { DPRINT(DBG_INFO, F("sendControlPacket cmd: 0x")); DBGHEXLN(cmd); initPacket(iv->radioId.u64, TX_REQ_DEVCONTROL, SINGLE_FRAME); @@ -101,6 +101,10 @@ class CmtRadio : public Radio { return iv->radioId.u64; } + uint8_t getIvGen(Inverter<> *iv) { + return iv->ivGen; + } + inline void reset(bool genDtuSn) { if(genDtuSn) generateDtuSn();