Skip to content

Commit 4dd0729

Browse files
author
Franz Reisenhofer
committed
added GA table caching
1 parent 1e6fbf5 commit 4dd0729

2 files changed

Lines changed: 46 additions & 46 deletions

File tree

usermods/KNX_IP/usermod_knx_ip.cpp

Lines changed: 39 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,24 @@
1+
// Helper: simple hash for config strings and segment offsets
2+
uint32_t KnxIpUsermod::computeGATableHash() const {
3+
// FNV-1a hash
4+
uint32_t hash = 2166136261u;
5+
auto hashstr = [&](const char* s) {
6+
while (*s) { hash ^= (uint8_t)(*s++); hash *= 16777619u; }
7+
};
8+
// Hash all GA strings
9+
const char* gaStrings[] = {
10+
gaInPower, gaInBri, gaInR, gaInG, gaInB, gaInW, gaInCct, gaInWW, gaInCW, gaInH, gaInS, gaInV, gaInFx, gaInPreset, gaInRGB, gaInHSV, gaInRGBW, gaInTime, gaInDate, gaInDateTime,
11+
gaInBriRel, gaInRRel, gaInGRel, gaInBRel, gaInWRel, gaInWWRel, gaInCWRel, gaInHRel, gaInSRel, gaInVRel, gaInFxRel, gaInRGBRel, gaInHSVRel, gaInRGBWRel,
12+
gaOutPower, gaOutBri, gaOutR, gaOutG, gaOutB, gaOutW, gaOutCct, gaOutWW, gaOutCW, gaOutH, gaOutS, gaOutV, gaOutFx, gaOutPreset, gaOutRGB, gaOutHSV, gaOutRGBW,
13+
gaOutIntTemp, gaOutTemp, gaOutIntTempAlarm, gaOutTempAlarm
14+
};
15+
for (const char* s : gaStrings) hashstr(s);
16+
// Hash segment offsets
17+
hash ^= segmentOffsetL; hash *= 16777619u;
18+
hash ^= segmentOffsetM; hash *= 16777619u;
19+
hash ^= segmentOffsetN; hash *= 16777619u;
20+
return hash;
21+
}
122
#include "usermod_knx_ip.h"
223
#include "wled.h" // access to global 'strip' and segments
324
#include "DPT.h"
@@ -1662,79 +1683,59 @@ String KnxIpUsermod::getGATableHTML() const {
16621683
KNX_UM_DEBUGF("[KNX-UM] getGATableHTML: usermod not enabled\n");
16631684
return "";
16641685
}
1665-
1666-
// Get current number of segments
16671686
uint8_t segmentCount = strip.getSegmentsNum();
1668-
if (segmentCount == 0) segmentCount = 1; // at least main segment
1669-
1670-
KNX_UM_DEBUGF("[KNX-UM] getGATableHTML: generating table for %d segments\n", segmentCount);
1671-
1672-
// Create table with better styling
1687+
if (segmentCount == 0) segmentCount = 1;
1688+
uint32_t hash = computeGATableHash();
1689+
if (gaTableCacheHash == hash && gaTableCacheSegments == segmentCount && gaTableCache.length() > 0) {
1690+
KNX_UM_DEBUGF("[KNX-UM] getGATableHTML: using cached table (%d chars)\n", gaTableCache.length());
1691+
return gaTableCache;
1692+
}
1693+
KNX_UM_DEBUGF("[KNX-UM] getGATableHTML: rebuilding table for %d segments\n", segmentCount);
1694+
// ...existing code...
1695+
// (copy the entire original function body here, but assign to gaTableCache and update gaTableCacheHash/gaTableCacheSegments)
16731696
String html = "<table style='font-size:11px;border-collapse:collapse;width:100%;'>";
16741697
html += "<tr style='background:#333;color:white;'><th style='border:1px solid #666;padding:4px;'>GA Type</th><th style='border:1px solid #666;padding:4px;'>Main</th>";
1675-
for (uint8_t seg = 1; seg < segmentCount && seg < 6; seg++) { // limit to 6 segments for display
1698+
for (uint8_t seg = 1; seg < segmentCount && seg < 6; seg++) {
16761699
html += "<th style='border:1px solid #666;padding:4px;'>Seg" + String(seg) + "</th>";
16771700
}
16781701
html += "</tr>";
1679-
1680-
// Helper to format GA (convert uint16_t back to a/b/c format)
16811702
auto formatGA = [](uint16_t ga) -> String {
16821703
if (ga == 0) return "-";
1683-
uint8_t main = (ga >> 11) & 0x1F;
1684-
uint8_t middle = (ga >> 8) & 0x07;
1685-
uint8_t sub = ga & 0xFF;
1704+
uint8_t main = (ga >> 11) & 0x1F;
1705+
uint8_t middle = (ga >> 8) & 0x07;
1706+
uint8_t sub = ga & 0xFF;
16861707
return String(main) + "/" + String(middle) + "/" + String(sub);
16871708
};
1688-
1689-
// Collect all GAs used across the entire table for global conflict detection
16901709
std::vector<uint16_t> allUsedGAs;
1691-
1692-
// Helper to add table row with conflict detection
16931710
auto addRow = [&](const char* label, const char* centralGA, const char* section = "", bool globalOnly = false) {
1694-
if (strlen(centralGA) == 0) return; // skip if GA not configured
1695-
1711+
if (strlen(centralGA) == 0) return;
16961712
html += "<tr><td style='border:1px solid #666;padding:2px 4px;color:white;'>" + String(label) + "</td>";
1697-
16981713
if (globalOnly) {
1699-
// For global GAs (Time, Date, Temperature), show only once in main column
17001714
uint16_t mainGA = parseGA(centralGA);
17011715
bool mainConflict = (mainGA > 0) && (std::find(allUsedGAs.begin(), allUsedGAs.end(), mainGA) != allUsedGAs.end());
17021716
if (mainGA > 0) allUsedGAs.push_back(mainGA);
1703-
17041717
String mainBg = mainConflict ? "background:#cc3333;" : "";
17051718
html += "<td style='border:1px solid #666;padding:2px 4px;color:white;" + mainBg + "'>" + formatGA(mainGA) + "</td>";
1706-
1707-
// Empty cells for other segments
17081719
for (uint8_t seg = 1; seg < segmentCount && seg < 6; seg++) {
17091720
html += "<td style='border:1px solid #666;padding:2px 4px;color:white;'>-</td>";
17101721
}
17111722
} else {
1712-
// For per-segment GAs, calculate for each segment
1713-
// Main segment (segment 0)
17141723
uint16_t mainGA = calculateSegmentGA(centralGA, 0);
17151724
bool mainConflict = (mainGA > 0) && (std::find(allUsedGAs.begin(), allUsedGAs.end(), mainGA) != allUsedGAs.end());
17161725
if (mainGA > 0) allUsedGAs.push_back(mainGA);
1717-
17181726
String mainBg = mainConflict ? "background:#cc3333;" : "";
17191727
html += "<td style='border:1px solid #666;padding:2px 4px;color:white;" + mainBg + "'>" + formatGA(mainGA) + "</td>";
1720-
1721-
// Other segments
17221728
for (uint8_t seg = 1; seg < segmentCount && seg < 6; seg++) {
17231729
uint16_t segGA = calculateSegmentGA(centralGA, seg);
17241730
bool segConflict = (segGA > 0) && (std::find(allUsedGAs.begin(), allUsedGAs.end(), segGA) != allUsedGAs.end());
17251731
if (segGA > 0) allUsedGAs.push_back(segGA);
1726-
17271732
String segBg = segConflict ? "background:#cc3333;" : "";
17281733
html += "<td style='border:1px solid #666;padding:2px 4px;color:white;" + segBg + "'>" + formatGA(segGA) + "</td>";
17291734
}
17301735
}
17311736
html += "</tr>";
17321737
};
1733-
1734-
// Add INPUT GAs section
17351738
html += "<tr><td colspan='" + String(1 + min((int)segmentCount, 6)) + "' style='border:1px solid #666;padding:4px;text-align:center;color:white;font-weight:bold;'>INPUT GAs (KNX → WLED)</td></tr>";
1736-
1737-
// Basic INPUT GAs
17381739
addRow("Power", gaInPower);
17391740
addRow("Brightness", gaInBri);
17401741
addRow("Red", gaInR);
@@ -1755,8 +1756,6 @@ String KnxIpUsermod::getGATableHTML() const {
17551756
addRow("Time", gaInTime, "", true);
17561757
addRow("Date", gaInDate, "", true);
17571758
addRow("DateTime", gaInDateTime, "", true);
1758-
1759-
// Relative INPUT GAs
17601759
addRow("Brightness Rel", gaInBriRel);
17611760
addRow("Red Rel", gaInRRel);
17621761
addRow("Green Rel", gaInGRel);
@@ -1771,11 +1770,7 @@ String KnxIpUsermod::getGATableHTML() const {
17711770
addRow("RGB Rel", gaInRGBRel);
17721771
addRow("HSV Rel", gaInHSVRel);
17731772
addRow("RGBW Rel", gaInRGBWRel);
1774-
1775-
// Add OUTPUT GAs section
17761773
html += "<tr><td colspan='" + String(1 + min((int)segmentCount, 6)) + "' style='border:1px solid #666;padding:4px;text-align:center;color:white;font-weight:bold;'>OUTPUT GAs (WLED → KNX)</td></tr>";
1777-
1778-
// Basic OUTPUT GAs
17791774
addRow("Power", gaOutPower);
17801775
addRow("Brightness", gaOutBri);
17811776
addRow("Red", gaOutR);
@@ -1797,15 +1792,13 @@ String KnxIpUsermod::getGATableHTML() const {
17971792
addRow("Temp Sensor", gaOutTemp, "", true);
17981793
addRow("Int Temp Alarm", gaOutIntTempAlarm, "", true);
17991794
addRow("Temp Alarm", gaOutTempAlarm, "", true);
1800-
18011795
html += "</table>";
1802-
1803-
// Add offset information
18041796
html += "<div style='font-size:10px;margin-top:4px;color:#aaa;'>Offsets: L=" + String(segmentOffsetL) + ", M=" + String(segmentOffsetM) + ", N=" + String(segmentOffsetN) + "</div>";
1805-
1797+
gaTableCache = html;
1798+
gaTableCacheHash = hash;
1799+
gaTableCacheSegments = segmentCount;
18061800
KNX_UM_DEBUGF("[KNX-UM] getGATableHTML: generated %d chars\n", html.length());
1807-
1808-
return html;
1801+
return gaTableCache;
18091802
}
18101803

18111804
// -------------------- Usermod API --------------------

usermods/KNX_IP/usermod_knx_ip.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@ class KnxIpUsermod : public Usermod {
3232
// --- Config values (editable via JSON/UI) ---
3333
bool enabled = true;
3434
char individualAddr[16] = "1.1.100";
35+
// --- GA Table cache ---
36+
mutable String gaTableCache;
37+
mutable uint32_t gaTableCacheHash = 0;
38+
mutable uint8_t gaTableCacheSegments = 0;
39+
void invalidateGATableCache() { gaTableCacheHash = 0; }
40+
// Helper to compute a hash of all GA strings and segment offsets
41+
uint32_t computeGATableHash() const;
3542

3643
// Inbound GAs (commands from KNX -> WLED)
3744
char gaInPower[16] = "1/0/1"; // DPT 1.001 (switch)

0 commit comments

Comments
 (0)