Browse Source

Merge branch 'rejoe2-development03' into development03

pull/1174/head
lumapu 1 year ago
parent
commit
0ff6c72a8e
  1. 11
      src/CHANGES.md
  2. 2
      src/defines.h
  3. 15
      src/hm/hmInverter.h
  4. 39
      src/hm/hmPayload.h
  5. 18
      src/hm/hmRadio.h
  6. 60
      src/hm/miPayload.h
  7. 2
      src/publisher/pubMqttIvData.h

11
src/CHANGES.md

@ -1,9 +1,14 @@
# Development Changes
## 0.7.59 - 2023-09-20
## 0.7.58 - 2023-09-19
* add another HM-600 hardware serial number #1169
* merge PR #1170
* reduce last_success MQTT messages (#1124)
* add re-request if inverter is known to be online and first try fails
* add alarm reporting to MI (might need review!)
* rebuild MI limiting code closer to DTUSimMI example
## 0.7.58
* fix ESP8266 save settings issue #1166
## 0.7.57 - 2023-09-18

2
src/defines.h

@ -13,7 +13,7 @@
//-------------------------------------
#define VERSION_MAJOR 0
#define VERSION_MINOR 7
#define VERSION_PATCH 58
#define VERSION_PATCH 59
//-------------------------------------
typedef struct {

15
src/hm/hmInverter.h

@ -212,18 +212,16 @@ class Inverter {
else if((alarmLastId != alarmMesIndex) && (alarmMesIndex != 0))
enqueCommand<InfoCommand>(AlarmData); // alarm not answered
enqueCommand<InfoCommand>(RealTimeRunData_Debug); // live data
} else if (ivGen == IV_MI){
} else { // if (ivGen == IV_MI){
if (getFwVersion() == 0) {
enqueCommand<InfoCommand>(InverterDevInform_All); // hard- and firmware version
} else {
record_t<> *rec = getRecordStruct(InverterDevInform_Simple);
if (getChannelFieldValue(CH0, FLD_PART_NUM, rec) == 0)
if (getChannelFieldValue(CH0, FLD_PART_NUM, rec) == 0) {
enqueCommand<InfoCommand>(InverterDevInform_All); // hard- and firmware version for missing HW part nr, delivered by frame 1
}
if (type == INV_TYPE_4CH) {
enqueCommand<InfoCommand>(0x36);
} else {
enqueCommand<InfoCommand>(0x09);
enqueCommand<InfoCommand>( type == INV_TYPE_4CH ? 0x36 : 0x09 );
}
}
}
@ -523,10 +521,7 @@ class Inverter {
rec->length = (uint8_t)(HMS1CH_LIST_LEN);
rec->assign = (byteAssign_t *)hms1chAssignment;
rec->pyldLen = HMS1CH_PAYLOAD_LEN;
} /*else if(IV_MI == ivGen) {
rec->length = (uint8_t)(HM1CH_LIST_LEN);
rec->assign = (byteAssign_t *)hm1chAssignment;
}*/
}
channels = 1;
}
else if (INV_TYPE_2CH == type) {

39
src/hm/hmPayload.h

@ -26,6 +26,7 @@ typedef struct {
uint8_t retransmits;
bool requested;
bool gotFragment;
bool rxTmo;
} invPayload_t;
@ -126,7 +127,7 @@ class HmPayload {
}
}
reset(iv->id);
reset(iv->id, !iv->isConnected);
mPayload[iv->id].requested = true;
yield();
@ -151,9 +152,11 @@ class HmPayload {
//iv->enqueCommand<InfoCommand>(SystemConfigPara); // read back power limit
} else {
uint8_t cmd = iv->getQueuedCmd();
if (mSerialDebug) {
DPRINT_IVID(DBG_INFO, iv->id);
DBGPRINT(F("prepareDevInformCmd 0x"));
DBGHEXLN(cmd);
}
mRadio->prepareDevInformCmd(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmLastId, false);
mPayload[iv->id].txCmd = cmd;
}
@ -199,6 +202,7 @@ class HmPayload {
} else
ok = false;
if (mSerialDebug) {
DPRINT_IVID(DBG_INFO, iv->id);
DBGPRINT(F(" has "));
if(!ok) DBGPRINT(F("not "));
@ -206,6 +210,7 @@ class HmPayload {
DBGPRINT(String(iv->powerLimit[0]));
DBGPRINT(F(" with PowerLimitControl "));
DBGPRINTLN(String(iv->powerLimit[1]));
}
iv->clearCmdQueue();
iv->enqueCommand<InfoCommand>(SystemConfigPara); // read back power limit
@ -249,15 +254,16 @@ class HmPayload {
mRadio->sendControlPacket(iv->radioId.u64, iv->devControlCmd, iv->powerLimit, true);
} else {
if(false == mPayload[iv->id].gotFragment) {
/*
DPRINTLN(DBG_WARN, F("nothing received: Request Complete Retransmit"));
mPayload[iv->id].txCmd = iv->getQueuedCmd();
DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") prepareDevInformCmd 0x") + String(mPayload[iv->id].txCmd, HEX));
mRadio->prepareDevInformCmd(iv->radioId.u64, mPayload[iv->id].txCmd, mPayload[iv->id].ts, iv->alarmLastId, true);
*/
DPRINT_IVID(DBG_INFO, iv->id);
DPRINT_IVID(DBG_WARN, iv->id);
if (mPayload[iv->id].rxTmo) {
DBGPRINTLN(F("nothing received"));
mPayload[iv->id].retransmits = mMaxRetrans;
} else {
DBGPRINTLN(F("nothing received: complete retransmit"));
mPayload[iv->id].txCmd = iv->getQueuedCmd();
DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") prepareDevInformCmd 0x") + String(mPayload[iv->id].txCmd, HEX));
mRadio->prepareDevInformCmd(iv->radioId.u64, mPayload[iv->id].txCmd, mPayload[iv->id].ts, iv->alarmMesIndex, true);
}
} else {
for (uint8_t i = 0; i < (mPayload[iv->id].maxPackId - 1); i++) {
if (mPayload[iv->id].len[i] == 0) {
@ -275,6 +281,9 @@ class HmPayload {
}
}
}
} else if (false == mPayload[iv->id].gotFragment) {
// only if there is no sign of life
mPayload[iv->id].rxTmo = true; // inv might be down, no complete retransmit anymore
}
} else if(!crcPass && pyldComplete) { // crc error on complete Payload
if (mPayload[iv->id].retransmits < mMaxRetrans) {
@ -300,6 +309,8 @@ class HmPayload {
}
record_t<> *rec = iv->getRecordStruct(mPayload[iv->id].txCmd); // choose the parser
mPayload[iv->id].complete = true;
mPayload[iv->id].requested = false;
mPayload[iv->id].rxTmo = false;
uint8_t payload[150];
uint8_t payloadLen = 0;
@ -355,7 +366,8 @@ class HmPayload {
yield();
}
}
if (fastNext) {
if (fastNext && (mHighPrioIv == NULL)) {
/*iv->setQueuedCmdFinished();
uint8_t cmd = iv->getQueuedCmd();
if (mSerialDebug) {
DPRINT_IVID(DBG_INFO, iv->id);
@ -366,6 +378,8 @@ class HmPayload {
mStat->rxSuccess++;
mRadio->prepareDevInformCmd(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmLastId, false);
mPayload[iv->id].txCmd = cmd;
*/
mHighPrioIv = iv;
}
} else {
@ -423,16 +437,14 @@ class HmPayload {
return false;
//requests to cause the next request to be executed immediately
if ( mPayload[iv->id].txCmd < 11 || mPayload[iv->id].txCmd > 18 ) {
if (mPayload[iv->id].gotFragment && ((mPayload[iv->id].txCmd < 11) || (mPayload[iv->id].txCmd > 18))) {
*fastNext = true;
//DPRINT_IVID(DBG_INFO, iv->id);
//DBGPRINTLN(F("fast next req"));
}
return true;
}
void reset(uint8_t id) {
void reset(uint8_t id, bool setTxTmo = true) {
//DPRINT_IVID(DBG_INFO, id);
//DBGPRINTLN(F("resetPayload"));
memset(mPayload[id].len, 0, MAX_PAYLOAD_ENTRIES);
@ -444,6 +456,7 @@ class HmPayload {
mPayload[id].complete = false;
mPayload[id].requested = false;
mPayload[id].ts = *mTimestamp;
mPayload[id].rxTmo = setTxTmo; // design: don't start with complete retransmit
}
IApp *mApp;

18
src/hm/hmRadio.h

@ -100,6 +100,7 @@ class HmRadio {
mNrf24.startListening();
mNrf24.setDataRate(RF24_250KBPS);
mNrf24.setAutoAck(true);
mNrf24.enableDynamicAck();
mNrf24.enableDynamicPayloads();
mNrf24.setCRCLength(RF24_CRC_16);
mNrf24.setAddressWidth(5);
@ -168,7 +169,7 @@ class HmRadio {
mSerialDebug = true;
}
void sendControlPacket(uint64_t invId, uint8_t cmd, uint16_t *data, bool isRetransmit, bool isNoMI = true) {
void sendControlPacket(uint64_t invId, uint8_t cmd, uint16_t *data, bool isRetransmit, bool isNoMI = true, bool is4chMI = false) {
DPRINT(DBG_INFO, F("sendControlPacket cmd: 0x"));
DBGHEXLN(cmd);
initPacket(invId, TX_REQ_DEVCONTROL, SINGLE_FRAME);
@ -194,10 +195,21 @@ class HmRadio {
mTxBuf[10] = 0x55;
break;
case ActivePowerContr:
cnt++;
mTxBuf[9] = 0x5a;
mTxBuf[10] = 0x5a;
mTxBuf[11] = data[0]; // power limit
//Testing only! Original NRF24_DTUMIesp.ino code #L612-L613:
//UsrData[0]=0x5A;UsrData[1]=0x5A;UsrData[2]=100;//0x0a;// 10% limit
//UsrData[3]=((Limit*10) >> 8) & 0xFF; UsrData[4]= (Limit*10) & 0xFF; //WR needs 1 dec= zB 100.1 W
if (is4chMI) {
mTxBuf[cnt++] = 100; //10% limit, seems to be necessary to send sth. at all, but for MI-1500 this has no effect
//works (if ever!) only for absulute power limits!
mTxBuf[cnt++] = ((data[0] * 10) >> 8) & 0xff; // power limit
mTxBuf[cnt++] = ((data[0] * 10) ) & 0xff; // power limit
} else {
mTxBuf[cnt++] = data[0]*10; // power limit
}
break;
default:
return;

60
src/hm/miPayload.h

@ -28,6 +28,7 @@ typedef struct {
bool gotFragment;
uint8_t rtrRes; // for limiting resets
uint8_t multi_parts; // for quality
bool rxTmo;
} miPayload_t;
@ -47,7 +48,7 @@ class MiPayload {
mMaxRetrans = maxRetransmits;
mTimestamp = timestamp;
for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) {
reset(i, true);
reset(i, false, true);
mPayload[i].limitrequested = true;
}
mSerialDebug = false;
@ -84,7 +85,7 @@ class MiPayload {
if (!mPayload[iv->id].complete)
process(false); // no retransmit
if (!mPayload[iv->id].complete) {
if (!mPayload[iv->id].complete && mPayload[iv->id].rxTmo) {
if (mSerialDebug)
DPRINT_IVID(DBG_INFO, iv->id);
if (!mPayload[iv->id].gotFragment) {
@ -100,13 +101,14 @@ class MiPayload {
DBGPRINTLN(F(")"));
}
}
mPayload[iv->id].rxTmo = true;
mPayload[iv->id].complete = true;
iv->setQueuedCmdFinished(); // command failed
}
}
}
reset(iv->id);
reset(iv->id, !iv->isConnected);
mPayload[iv->id].requested = true;
yield();
@ -125,12 +127,11 @@ class MiPayload {
DBGPRINTLN(String(iv->powerLimit[0]));
}
iv->powerLimitAck = false;
mRadio->sendControlPacket(iv->radioId.u64, iv->devControlCmd, iv->powerLimit, false, false);
mRadio->sendControlPacket(iv->radioId.u64, iv->devControlCmd, iv->powerLimit, false, false, iv->type == INV_TYPE_4CH);
mPayload[iv->id].txCmd = iv->devControlCmd;
mPayload[iv->id].limitrequested = true;
iv->clearCmdQueue();
//iv->enqueCommand<InfoCommand>(SystemConfigPara); // read back power limit is not possible with MI
} else {
uint8_t cmd = iv->getQueuedCmd();
uint8_t cmd2 = cmd;
@ -311,6 +312,7 @@ class MiPayload {
mPayload[iv->id].txCmd != 0x0f)) {
// no processing needed if txId is not one of 0x95, 0x88, 0x89, 0x91, 0x92 or response to 0x36ff
mPayload[iv->id].complete = true;
mPayload[iv->id].rxTmo = true;
continue; // skip to next inverter
}
@ -324,6 +326,7 @@ class MiPayload {
DPRINT_IVID(DBG_INFO, iv->id);
DBGPRINTLN(F("Prevent retransmit on Restart / CleanState_LockAndAlarm..."));
mPayload[iv->id].retransmits = mMaxRetrans;
mPayload[iv->id].rxTmo = true;
} else if(iv->devControlCmd == ActivePowerContr) {
DPRINT_IVID(DBG_INFO, iv->id);
DBGPRINTLN(F("retransmit power limit"));
@ -332,10 +335,15 @@ class MiPayload {
uint8_t cmd = mPayload[iv->id].txCmd;
if (mPayload[iv->id].retransmits < mMaxRetrans) {
mPayload[iv->id].retransmits++;
if( !mPayload[iv->id].gotFragment ) {
if( !mPayload[iv->id].gotFragment && mPayload[iv->id].rxTmo ) {
DPRINT_IVID(DBG_INFO, iv->id);
DBGPRINTLN(F("nothing received"));
mPayload[iv->id].retransmits = mMaxRetrans;
} else if( !mPayload[iv->id].gotFragment && !mPayload[iv->id].rxTmo ) {
DPRINT_IVID(DBG_INFO, iv->id);
DBGPRINTLN(F("retransmit on failed first request"));
mPayload[iv->id].rxTmo = true;
mRadio->sendCmdPacket(iv->radioId.u64, cmd, cmd, true, false);
} else if ( cmd == 0x0f ) {
//hard/firmware request
mRadio->sendCmdPacket(iv->radioId.u64, 0x0f, 0x00, true, false);
@ -379,6 +387,8 @@ class MiPayload {
mRadio->sendCmdPacket(iv->radioId.u64, cmd, cmd, true, false);
yield();
}
} else {
mPayload[iv->id].rxTmo = true;
}
}
}
@ -395,9 +405,14 @@ class MiPayload {
DBGHEXLN(mPayload[iv->id].txCmd);
}
mRadio->sendCmdPacket(iv->radioId.u64, mPayload[iv->id].txCmd, mPayload[iv->id].txCmd, false, false);
} else {
mPayload[iv->id].rxTmo = true;
}
} else {
if (fastNext) {
if (!fastNext) {
mPayload[iv->id].rxTmo = true;
} else {
/*iv->setQueuedCmdFinished();
uint8_t cmd = iv->getQueuedCmd();
if (mSerialDebug) {
DPRINT_IVID(DBG_INFO, iv->id);
@ -406,11 +421,16 @@ class MiPayload {
DBGHEXLN(cmd);
}
mStat->rxSuccess++;
mRadio->prepareDevInformCmd(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex, false);
mPayload[iv->id].txCmd = cmd;
//mRadio->prepareDevInformCmd(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex, false);
mRadio->prepareDevInformCmd(iv->radioId.u64, iv->getType(),
iv->getNextTxChanIndex(), cmd, mPayload[iv->id].ts, iv->alarmMesIndex, false);
mPayload[iv->id].txCmd = cmd; */
if (mHighPrioIv == NULL)
mHighPrioIv = iv;
}
}
} else {
mPayload[iv->id].rxTmo = true;
}
yield();
}
@ -456,6 +476,15 @@ class MiPayload {
uint16_t prntsts = statusMi == 3 ? 1 : statusMi;
if ( statusMi != mPayload[iv->id].sts[stschan] ) { //sth.'s changed?
iv->alarmCnt = 1; // minimum...
if (iv->type != INV_TYPE_1CH && ( statusMi != 3 //sth is or was wrong!
|| mPayload[iv->id].sts[stschan] && statusMi == 3 && mPayload[iv->id].sts[stschan] != 3)
) {
iv->lastAlarm[stschan] = alarm_t(prntsts, mPayload[iv->id].ts,mPayload[iv->id].ts);
iv->alarmCnt = iv->type == INV_TYPE_2CH ? 3 : 5;
iv->alarmLastId = iv->alarmMesIndex;
}
mPayload[iv->id].sts[stschan] = statusMi;
if (mSerialDebug) {
DPRINT(DBG_WARN, F("New state on CH"));
@ -477,6 +506,7 @@ class MiPayload {
DBGPRINT(F("alarm ID incremented to "));
DBGPRINTLN(String(iv->alarmMesIndex));
}
iv->lastAlarm[0] = alarm_t(prntsts, mPayload[iv->id].ts, mPayload[iv->id].ts);
}
/*if(AlarmData == mPayload[iv->id].txCmd) {
uint8_t i = 0;
@ -584,6 +614,7 @@ class MiPayload {
uint8_t txCmd = mPayload[iv->id].txCmd;
if(!*complete) {
DPRINTLN(DBG_VERBOSE, F("incomlete, txCmd is 0x") + String(txCmd, HEX));
//we got some delayed status msgs?!?
if ((txCmd == 0x09) || (txCmd == 0x11)) {
if (mPayload[iv->id].stsAB[CH0] && mPayload[iv->id].dataAB[CH0]) {
@ -592,8 +623,6 @@ class MiPayload {
}
return false;
}
DPRINTLN(DBG_VERBOSE, F("incomlete, txCmd is 0x") + String(txCmd, HEX));
if (txCmd >= 0x36 && txCmd <= 0x39) {
return false;
}
@ -607,7 +636,7 @@ class MiPayload {
}
//check if we want the next request to be executed faster
if (txCmd == 0x0f)
if (mPayload[iv->id].gotFragment && txCmd == 0x0f)
*fastNext = true;
return true;
}
@ -725,14 +754,16 @@ const byteAssign_t InfoAssignment[] = {
if (mPayload[iv->id].multi_parts > 5) {
iv->setQueuedCmdFinished();
mPayload[iv->id].complete = true;
mPayload[iv->id].rxTmo = true;
mPayload[iv->id].requested= false;
mStat->rxSuccess++;
}
}
void reset(uint8_t id, bool clrSts = false) {
void reset(uint8_t id, bool setTxTmo = true, bool clrSts = false) {
memset(mPayload[id].len, 0, MAX_PAYLOAD_ENTRIES);
mPayload[id].gotFragment = false;
mPayload[id].rxTmo = setTxTmo;// design: don't start with complete retransmit
mPayload[id].rtrRes = 0;
mPayload[id].multi_parts = 0;
mPayload[id].retransmits = 0;
@ -744,7 +775,6 @@ const byteAssign_t InfoAssignment[] = {
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].skipfirstrepeat = 0;
mPayload[id].requested = false;
mPayload[id].ts = *mTimestamp;
mPayload[id].sts[0] = 0;

2
src/publisher/pubMqttIvData.h

@ -103,7 +103,7 @@ class PubMqttIvData {
mPos = 0;
if(found) {
record_t<> *rec = mIv->getRecordStruct(mCmd);
if(mIv->getLastTs(rec) != mIvLastPublish[mIv->id]) {
if((mIv->getLastTs(rec) != mIvLastPublish[mIv->id]) && mIv->getLastTs(rec) != 0 ) { //workaround for startup. Suspect, mCmd might cause to much messages....
snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "%s/last_success", mIv->config->name);
snprintf(mVal, 40, "%d", mIv->getLastTs(rec));
mPublish(mSubTopic, mVal, true, QOS_0);

Loading…
Cancel
Save