From 3fdc403a07778ade96ece8d01587c1d93abae369 Mon Sep 17 00:00:00 2001 From: 123fenix Date: Fri, 31 Jul 2026 13:00:40 +0200 Subject: [PATCH 1/3] Add HMS2000 diagnostic logging --- src/hm/Communication.h | 58 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/src/hm/Communication.h b/src/hm/Communication.h index 6290fc31..22bbcdbe 100644 --- a/src/hm/Communication.h +++ b/src/hm/Communication.h @@ -242,6 +242,7 @@ class Communication : public CommQueue<> { break; case States::CHECK_PACKAGE: + printFrameMap(q, F("check")); uint8_t framnr = 0; if(0 == mMaxFrameId) { uint8_t i = 0; @@ -296,6 +297,7 @@ class Communication : public CommQueue<> { q->setAttempt(); if(*mSerialDebug) { + printFrameMap(q, F("before retransmit")); DPRINT_IVID(DBG_WARN, q->iv->id); DBGPRINT(F("frame ")); DBGPRINT(String(framnr)); @@ -420,6 +422,42 @@ class Communication : public CommQueue<> { return (ah::crc8(buf, len - 1) == buf[len-1]); } + inline void printFrameMap(QueueElement *q, const char *stage) { + if(!*mSerialDebug) + return; + + DPRINT_IVID(DBG_INFO, q->iv->id); + DBGPRINT(stage); + DBGPRINT(F(" frames: max=")); + DBGPRINT(String(mMaxFrameId)); + DBGPRINT(F(" received=[")); + bool first = true; + uint8_t limit = (mMaxFrameId > 0) ? mMaxFrameId : MAX_PAYLOAD_ENTRIES; + for(uint8_t i = 0; i < limit; i++) { + if(mLocalBuf[i].len > 0) { + if(!first) DBGPRINT(F(",")); + DBGPRINT(String(i + 1)); + DBGPRINT(F("(")); + DBGPRINT(String(mLocalBuf[i].len)); + DBGPRINT(F("B)")); + first = false; + } + } + DBGPRINT(F("] missing=[")); + first = true; + for(uint8_t i = 0; i < limit; i++) { + if(mLocalBuf[i].len == 0) { + if(!first) DBGPRINT(F(",")); + DBGPRINT(String(i + 1)); + first = false; + } + } + DBGPRINT(F("] attempts=")); + DBGPRINT(String(q->attempts)); + DBGPRINT(F(" retransmit=")); + DBGPRINTLN(mIsRetransmit ? F("yes") : F("no")); + } + inline bool parseFrame(QueueElement *q, packet_t *p) { uint8_t *frameId = &p->packet[9]; if(0x00 == *frameId) { @@ -447,6 +485,19 @@ class Communication : public CommQueue<> { f->len = p->len - 11; f->rssi = p->rssi; + if(*mSerialDebug) { + DPRINT_IVID(DBG_INFO, q->iv->id); + DBGPRINT(F("stored frame ")); + DBGPRINT(String(*frameId & 0x7f)); + DBGPRINT(F(" last=")); + DBGPRINT((*frameId & ALL_FRAMES) ? F("yes") : F("no")); + DBGPRINT(F(" bytes=")); + DBGPRINT(String(f->len)); + DBGPRINT(F(" max=")); + DBGPRINTLN(String(mMaxFrameId)); + printFrameMap(q, F("after RX")); + } + return true; } @@ -613,6 +664,13 @@ class Communication : public CommQueue<> { } void sendRetransmit(QueueElement *q, uint8_t i) { + if(*mSerialDebug) { + DPRINT_IVID(DBG_INFO, q->iv->id); + DBGPRINT(F("send retransmit request: frame=")); + DBGPRINT(String(i + 1)); + DBGPRINT(F(" cmd=0x")); + DBGHEXLN(SINGLE_FRAME + i); + } mFramesExpected = 1; q->iv->radio->setExpectedFrames(mFramesExpected); q->iv->radio->sendCmdPacket(q->iv, TX_REQ_INFO, (SINGLE_FRAME + i), true); From 9a6351e897916ec19bb857950d278e45540f665b Mon Sep 17 00:00:00 2001 From: 123fenix Date: Fri, 31 Jul 2026 13:38:10 +0200 Subject: [PATCH 2/3] Increase HMS2000 retransmit attempts for diagnostics --- src/hm/CommQueue.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hm/CommQueue.h b/src/hm/CommQueue.h index 8f11c31c..c01718c6 100644 --- a/src/hm/CommQueue.h +++ b/src/hm/CommQueue.h @@ -26,7 +26,7 @@ template #endif class CommQueue { protected: /* types */ - static constexpr uint8_t DefaultAttempts = 5; + static constexpr uint8_t DefaultAttempts = 13; static constexpr uint8_t MoreAttemptsAlarmData = 3; static constexpr uint8_t MoreAttemptsGridProfile = 0; From dc3e05939928927a51dbe83a4acbeb1c52c055b6 Mon Sep 17 00:00:00 2001 From: 123fenix Date: Fri, 31 Jul 2026 15:33:34 +0200 Subject: [PATCH 3/3] Make HMS packet diagnostics optional at compile time Detailed HMS frame-map and retransmission diagnostics were useful while investigating incomplete multi-frame responses from HMS-2000-4T inverters. However, the additional output can overflow the WebSerial buffer and affect responsiveness during normal operation. Wrap the additional diagnostics with the AHOY_HMS_DIAGNOSTICS compile-time switch. The diagnostics are disabled by default and can be enabled with -DAHOY_HMS_DIAGNOSTICS=1. Normal Ahoy logging and retransmission behavior remain unchanged. --- src/hm/Communication.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/hm/Communication.h b/src/hm/Communication.h index 22bbcdbe..6c2edcab 100644 --- a/src/hm/Communication.h +++ b/src/hm/Communication.h @@ -242,7 +242,9 @@ class Communication : public CommQueue<> { break; case States::CHECK_PACKAGE: +#if AHOY_HMS_DIAGNOSTICS printFrameMap(q, F("check")); +#endif uint8_t framnr = 0; if(0 == mMaxFrameId) { uint8_t i = 0; @@ -297,7 +299,9 @@ class Communication : public CommQueue<> { q->setAttempt(); if(*mSerialDebug) { +#if AHOY_HMS_DIAGNOSTICS printFrameMap(q, F("before retransmit")); +#endif DPRINT_IVID(DBG_WARN, q->iv->id); DBGPRINT(F("frame ")); DBGPRINT(String(framnr)); @@ -422,6 +426,7 @@ class Communication : public CommQueue<> { return (ah::crc8(buf, len - 1) == buf[len-1]); } +#if AHOY_HMS_DIAGNOSTICS inline void printFrameMap(QueueElement *q, const char *stage) { if(!*mSerialDebug) return; @@ -457,6 +462,7 @@ class Communication : public CommQueue<> { DBGPRINT(F(" retransmit=")); DBGPRINTLN(mIsRetransmit ? F("yes") : F("no")); } +#endif inline bool parseFrame(QueueElement *q, packet_t *p) { uint8_t *frameId = &p->packet[9]; @@ -485,6 +491,7 @@ class Communication : public CommQueue<> { f->len = p->len - 11; f->rssi = p->rssi; +#if AHOY_HMS_DIAGNOSTICS if(*mSerialDebug) { DPRINT_IVID(DBG_INFO, q->iv->id); DBGPRINT(F("stored frame ")); @@ -497,6 +504,7 @@ class Communication : public CommQueue<> { DBGPRINTLN(String(mMaxFrameId)); printFrameMap(q, F("after RX")); } +#endif return true; } @@ -664,6 +672,7 @@ class Communication : public CommQueue<> { } void sendRetransmit(QueueElement *q, uint8_t i) { +#if AHOY_HMS_DIAGNOSTICS if(*mSerialDebug) { DPRINT_IVID(DBG_INFO, q->iv->id); DBGPRINT(F("send retransmit request: frame=")); @@ -671,6 +680,7 @@ class Communication : public CommQueue<> { DBGPRINT(F(" cmd=0x")); DBGHEXLN(SINGLE_FRAME + i); } +#endif mFramesExpected = 1; q->iv->radio->setExpectedFrames(mFramesExpected); q->iv->radio->sendCmdPacket(q->iv, TX_REQ_INFO, (SINGLE_FRAME + i), true);