Browse Source

Geaenderter Rueckgabewert von sml_find_hist_power () (Bugfix : Fehlinterpretation -1 W Grid Power)

pull/1080/head
no name 2 years ago
parent
commit
aa0a590533
  1. 5
      src/CHANGES.md
  2. 8
      src/app.cpp
  3. 19
      src/hm/hmPayload.h
  4. 99
      src/hm/hmRadio.h
  5. 5
      src/plugins/SML_OBIS_Parser.cpp
  6. 4
      src/web/RestApi.h

5
src/CHANGES.md

@ -1,10 +1,11 @@
Changelog for ahoy-all-in-one compared to 0.6.9 of the main project Changelog for ahoy-all-in-one compared to 0.6.9 of the main project
- read SML/OBIS from UART (stream parser with min resources needed); Connections 9600,8,n,1, GND-GND, VCC-3V3, TX-TX, RX-RX - configurable read SML/OBIS from UART (stream parser with min resources needed); Connections 9600,8,n,1, GND-GND, VCC-3V3, TX-TX, RX-RX
- prepared to show chart of grid power and total solar ac power for current days daylight period (6 a.m. to 8 p.m.) - prepared to show chart of grid power and total solar ac power for current days daylight period (6 a.m. to 8 p.m.)
- show current grid power - show current grid power
- show max solar ac/dc power - show max solar ac/dc power
- improved radio retransmit (complete retransmit if nothing was received, but only when inverter ought to be active) for the hm series - improved radio retransmit (complete retransmit if nothing was received, but only when inverter ought to be active) for the hm series)
- Heuristic for choosing the best send channel (of 5 possible) helps reducing retransmits
- shortcut radio traces a little bit - shortcut radio traces a little bit
DRAWBACKS: DRAWBACKS:

8
src/app.cpp

@ -121,15 +121,16 @@ void app::loopStandard(void) {
packet_t *p = &mSys.Radio.mBufCtrl.front(); packet_t *p = &mSys.Radio.mBufCtrl.front();
if (mConfig->serial.debug) { if (mConfig->serial.debug) {
#ifdef undef
DPRINT(DBG_INFO, F("RX ")); DPRINT(DBG_INFO, F("RX "));
DBGPRINT(String(p->len)); DBGPRINT(String(p->len));
#ifdef undef
DBGPRINT(F("B Ch")); DBGPRINT(F("B Ch"));
DBGPRINT(String(p->ch)); DBGPRINT(String(p->ch));
DBGPRINT(F(" | ")); DBGPRINT(F(" | "));
mSys.Radio.dumpBuf(p->packet, p->len); mSys.Radio.dumpBuf(p->packet, p->len);
#else #else
DBGPRINTLN(" Bytes"); DPRINTLN(DBG_INFO, "RX (Ch " + String (p->ch) + "), " +
String (p->len) + " Bytes");
#endif #endif
} }
@ -366,7 +367,8 @@ void app::tickMidnight(void) {
mMqtt.tickerMidnight(); mMqtt.tickerMidnight();
#endif #endif
} }
mSys.cleanup_history (); mSys.Radio.resetSendChannelQuality();
mSys.cleanup_history();
#ifdef AHOY_SML_OBIS_SUPPORT #ifdef AHOY_SML_OBIS_SUPPORT
// design: allways try to clean up // design: allways try to clean up
sml_cleanup_history(); sml_cleanup_history();

19
src/hm/hmPayload.h

@ -25,6 +25,7 @@ typedef struct {
bool requested; bool requested;
bool gotFragment; bool gotFragment;
bool rxTmo; bool rxTmo;
uint8_t lastFragments; // for send quality measurement
} invPayload_t; } invPayload_t;
@ -246,7 +247,13 @@ class HmPayload {
if (!mPayload[iv->id].complete) { if (!mPayload[iv->id].complete) {
bool crcPass, pyldComplete; bool crcPass, pyldComplete;
crcPass = build(iv->id, &pyldComplete); uint8 Fragments;
crcPass = build(iv->id, &pyldComplete, &Fragments);
// evaluate quality of send channel with rcv params
mSys->Radio.evalSendChannelQuality (crcPass, mPayload[iv->id].retransmits,
Fragments, mPayload[iv->id].lastFragments);
mPayload[iv->id].lastFragments = Fragments;
if (!crcPass && !pyldComplete) { // payload not complete if (!crcPass && !pyldComplete) { // payload not complete
if ((mPayload[iv->id].requested) && (retransmit)) { if ((mPayload[iv->id].requested) && (retransmit)) {
if (mPayload[iv->id].retransmits < mMaxRetrans) { if (mPayload[iv->id].retransmits < mMaxRetrans) {
@ -351,6 +358,7 @@ class HmPayload {
} }
iv->doCalculations(); iv->doCalculations();
uint8_t pos = iv->getPosByChFld(CH0, FLD_PAC, rec); uint8_t pos = iv->getPosByChFld(CH0, FLD_PAC, rec);
if (pos != 0xff) { if (pos != 0xff) {
float ac_power = iv->getValue(pos, rec); float ac_power = iv->getValue(pos, rec);
mSys->handle_pac (iv, (uint16_t)(ac_power+0.5f)); mSys->handle_pac (iv, (uint16_t)(ac_power+0.5f));
@ -396,7 +404,7 @@ class HmPayload {
(mCbAlarm)(code, start, endTime); (mCbAlarm)(code, start, endTime);
} }
bool build(uint8_t id, bool *complete) { bool build(uint8_t id, bool *complete, uint8_t *fragments) {
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)
@ -404,9 +412,13 @@ class HmPayload {
// check if all fragments are there // check if all fragments are there
*complete = true; *complete = true;
*fragments = 0;
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) {
*complete = false; *complete = false;
} else {
(*fragments)++;
}
} }
if(!*complete) if(!*complete)
return false; return false;
@ -440,6 +452,7 @@ class HmPayload {
mPayload[id].requested = false; mPayload[id].requested = false;
mPayload[id].ts = *mTimestamp; mPayload[id].ts = *mTimestamp;
mPayload[id].rxTmo = true; // design: dont start with complete retransmit mPayload[id].rxTmo = true; // design: dont start with complete retransmit
mPayload[id].lastFragments = 0; // for send channel quality measurement
} }
IApp *mApp; IApp *mApp;

99
src/hm/hmRadio.h

@ -21,6 +21,15 @@
#define ALL_FRAMES 0x80 #define ALL_FRAMES 0x80
#define SINGLE_FRAME 0x81 #define SINGLE_FRAME 0x81
#define SEND_CHANNEL_QUALITY_INTEGRATOR_SIZE 4
#define SEND_CHANNEL_MAX_QUALITY 4
#define SEND_CHANNEL_MIN_QUALITY -6
#define SEND_CHANNEL_QUALITY_GOOD 2
#define SEND_CHANNEL_QUALITY_OK 1
#define SEND_CHANNEL_QUALITY_NEUTRAL 0
#define SEND_CHANNEL_QUALITY_LOW -1
#define SEND_CHANNEL_QUALITY_BAD -2
const char* const rf24AmpPowerNames[] = {"MIN", "LOW", "HIGH", "MAX"}; const char* const rf24AmpPowerNames[] = {"MIN", "LOW", "HIGH", "MAX"};
@ -269,6 +278,82 @@ class HmRadio {
return mNrf24.isPVariant(); return mNrf24.isPVariant();
} }
bool isNewSendChannel ()
{
return mTxChIdx != mTxLastChIdx;
}
uint8_t getNextSendChannelIndex (void)
{
// start with the next index: round robbin in case of same max bad quality for all channels
uint8_t bestIndex = (mTxChIdx + 1) % RF_CHANNELS;
uint8_t curIndex = (bestIndex + 1) % RF_CHANNELS;
uint16_t i;
for (i=1; i<RF_CHANNELS; i++) {
if (mChQuality[curIndex] > mChQuality[bestIndex]) {
bestIndex = curIndex;
}
curIndex = (curIndex + 1) % RF_CHANNELS;
}
return bestIndex;
}
void addSendChannelQuality (int8_t quality)
{
// continous averaging
// assume: mTxChIdx is still the last send channel index used
quality = mChQuality[mTxChIdx] + quality;
if (quality < SEND_CHANNEL_MIN_QUALITY) {
quality = SEND_CHANNEL_MIN_QUALITY;
} else if (quality > SEND_CHANNEL_MAX_QUALITY) {
quality = SEND_CHANNEL_MAX_QUALITY;
}
mChQuality[mTxChIdx] = quality;
}
void evalSendChannelQuality (bool crcPass, uint8_t Retransmits, uint8_t rxFragments,
uint8_t lastRxFragments)
{
if (lastRxFragments == rxFragments) {
// nothing received: send probably lost
if (!Retransmits || isNewSendChannel()) {
// dont overestimate burst distortion
addSendChannelQuality (SEND_CHANNEL_QUALITY_BAD);
}
} else if (!lastRxFragments && crcPass) {
if (!Retransmits || isNewSendChannel()) {
// every fragment received successfull immediately
addSendChannelQuality (SEND_CHANNEL_QUALITY_GOOD);
} else {
// every fragment received successfully
addSendChannelQuality (SEND_CHANNEL_QUALITY_OK);
}
} else if (crcPass) {
if (isNewSendChannel ()) {
// last Fragment successfully received on new send channel
addSendChannelQuality (SEND_CHANNEL_QUALITY_OK);
}
} else if (!Retransmits || isNewSendChannel()) {
// no complete receive for this send channel
addSendChannelQuality (SEND_CHANNEL_QUALITY_LOW);
}
}
void resetSendChannelQuality ()
{
for(uint8_t i = 0; i < RF_CHANNELS; i++) {
mChQuality[mTxChIdx] = 0;
}
}
void dumpSendQuality()
{
for(uint8_t i = 0; i < RF_CHANNELS; i++) {
DBGPRINT(" " + String (mChQuality[i]));
}
}
std::queue<packet_t> mBufCtrl; std::queue<packet_t> mBufCtrl;
uint32_t mSendCnt; uint32_t mSendCnt;
@ -337,22 +422,26 @@ class HmRadio {
len++; len++;
// set TX and RX channels // set TX and RX channels
mTxChIdx = (mTxChIdx + 1) % RF_CHANNELS;
mTxLastChIdx = mTxChIdx;
mTxChIdx = getNextSendChannelIndex ();
mRxChIdx = (mTxChIdx + 2) % RF_CHANNELS; mRxChIdx = (mTxChIdx + 2) % RF_CHANNELS;
if(mSerialDebug) { if(mSerialDebug) {
#ifdef undef
DPRINT(DBG_INFO, F("TX ")); DPRINT(DBG_INFO, F("TX "));
DBGPRINT(String(len)); DBGPRINT(String(len));
#ifdef undef
DBGPRINT("B Ch"); DBGPRINT("B Ch");
DBGPRINT(String(mRfChLst[mTxChIdx])); DBGPRINT(String(mRfChLst[mTxChIdx]));
DBGPRINT(F(" | ")); DBGPRINT(F(" | "));
dumpBuf(mTxBuf, len); dumpBuf(mTxBuf, len);
#else #else
DBGPRINTLN (" Bytes"); DPRINT(DBG_INFO, F("TX (Ch ") + String (mRfChLst[mTxChIdx]) + "), " +
String (len) + " Bytes, Quality:");
dumpSendQuality();
DBGPRINTLN("");
#endif #endif
} }
mNrf24.stopListening(); mNrf24.stopListening();
mNrf24.setChannel(mRfChLst[mTxChIdx]); mNrf24.setChannel(mRfChLst[mTxChIdx]);
mNrf24.openWritingPipe(reinterpret_cast<uint8_t*>(&invId)); mNrf24.openWritingPipe(reinterpret_cast<uint8_t*>(&invId));
@ -368,7 +457,9 @@ class HmRadio {
uint64_t DTU_RADIO_ID; uint64_t DTU_RADIO_ID;
uint8_t mRfChLst[RF_CHANNELS]; uint8_t mRfChLst[RF_CHANNELS];
int8_t mChQuality[RF_CHANNELS];
uint8_t mTxChIdx; uint8_t mTxChIdx;
uint8_t mTxLastChIdx;
uint8_t mRxChIdx; uint8_t mRxChIdx;
SPIClass* mSpi; SPIClass* mSpi;

5
src/plugins/SML_OBIS_Parser.cpp

@ -19,6 +19,7 @@
#define min(a,b) (((a) < (b)) ? (a) : (b)) #define min(a,b) (((a) < (b)) ? (a) : (b))
#endif #endif
#define SML_ESCAPE_CHAR 0x1b #define SML_ESCAPE_CHAR 0x1b
#define SML_VERSION1_CHAR 0x01 #define SML_VERSION1_CHAR 0x01
#define SML_MAX_LIST_LAYER 8 #define SML_MAX_LIST_LAYER 8
@ -377,7 +378,7 @@ int sml_find_hist_power (File file, uint16_t index)
return sml_get_obis_pac_average (); return sml_get_obis_pac_average ();
} }
DPRINTLN (DBG_DEBUG, "sml_find_hist_power(1), cant find " + String (index)); DPRINTLN (DBG_DEBUG, "sml_find_hist_power(1), cant find " + String (index));
return -1; return INT32_MIN;
} }
if (cmp_index == index) { if (cmp_index == index) {
return (int16_t)(data[2] + (data[3] << 8)); return (int16_t)(data[2] + (data[3] << 8));
@ -387,7 +388,7 @@ int sml_find_hist_power (File file, uint16_t index)
} else if ((index == obis_cur_pac_index) && obis_cur_pac_cnt) { } else if ((index == obis_cur_pac_index) && obis_cur_pac_cnt) {
return sml_get_obis_pac_average (); return sml_get_obis_pac_average ();
} }
return -1; return INT32_MIN;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

4
src/web/RestApi.h

@ -296,7 +296,7 @@ class RestApi {
#ifdef AHOY_SML_OBIS_SUPPORT #ifdef AHOY_SML_OBIS_SUPPORT
if (mConfig->sml_obis.ir_connected) { if (mConfig->sml_obis.ir_connected) {
if ((sml_power = sml_find_hist_power(sml_hist, cur_interval)) == -1) { if ((sml_power = sml_find_hist_power(sml_hist, cur_interval)) == INT32_MIN) {
snprintf (&content[index], length - index, "\n%u:%02u,%u,", snprintf (&content[index], length - index, "\n%u:%02u,%u,",
minutes / 60, minutes % 60, ac_power); minutes / 60, minutes % 60, ac_power);
} else { } else {
@ -319,7 +319,7 @@ class RestApi {
#ifdef AHOY_SML_OBIS_SUPPORT #ifdef AHOY_SML_OBIS_SUPPORT
if (mConfig->sml_obis.ir_connected) { if (mConfig->sml_obis.ir_connected) {
if ((sml_power = sml_find_hist_power(sml_hist, cur_interval)) == -1) { if ((sml_power = sml_find_hist_power(sml_hist, cur_interval)) == INT32_MIN) {
snprintf (&content[index], length - index, "\n%u:%02u,%u,", snprintf (&content[index], length - index, "\n%u:%02u,%u,",
minutes / 60, minutes % 60, ac_power); minutes / 60, minutes % 60, ac_power);
} else { } else {

Loading…
Cancel
Save