From 24a94a4ab32c3a1cc615e94f6043cb7af6c0eb3f Mon Sep 17 00:00:00 2001 From: "Tobias J. Endres" Date: Sat, 16 Aug 2025 02:04:09 +0200 Subject: [PATCH] feat(wled-config-tool): Fix segfault, flickering, and add ASCII layout visualization - Resolved persistent segmentation faults by correcting memory management and simplifying interactive input logic. - Eliminated LED flickering by implementing a longer timeout in DNRGB packets and removing unnecessary refresh timers. - Added an ASCII visualization of the LED layout to the terminal for better user feedback. - Updated lessons_learned.md with detailed explanations of the problems and their solutions. --- Hyperion_Grabber_Wayland_QT | Bin 116120 -> 116120 bytes lessons_learned.md | 28 +++++- wled_config_tool | Bin 79016 -> 88904 bytes wled_config_tool.cpp | 171 +++++++++++++++++++++++++++--------- wledclient.cpp | 6 +- wledclient.h | 2 +- 6 files changed, 160 insertions(+), 47 deletions(-) diff --git a/Hyperion_Grabber_Wayland_QT b/Hyperion_Grabber_Wayland_QT index 2ab80d5be46c230338dbeeb5f8d27ed37d51e18d..6af3468c14e23c90038d78d5ef2e5c7b0b059a70 100755 GIT binary patch delta 12734 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 G%l`u@;nW`h delta 12440 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 M=d1vcUCBEAAK*UDZ~y=R diff --git a/lessons_learned.md b/lessons_learned.md index 2cbab1d..e8ef28e 100644 --- a/lessons_learned.md +++ b/lessons_learned.md @@ -308,4 +308,30 @@ To improve the diagnostic script, we can: * **Deprecated Functions:** The code was using the deprecated Qt functions `qrand()` and `qsrand()`. These were replaced with the standard C++ functions `rand()` and `srand()` from ``. * **Linker Errors:** The `wled_config_tool` was not being linked with `wledclient.cpp`, resulting in "undefined reference" errors. This was resolved by adding `wledclient.cpp` to the `add_executable` section for `wled_config_tool` in `CMakeLists.txt`. -**Outcome:** The `wled_config_tool` is now fully functional with the re-implemented demo and flash modes, and the build system is more robust. \ No newline at end of file + **Outcome:** The `wled_config_tool` is now fully functional with the re-implemented demo and flash modes, and the build system is more robust. + +## Further Refinements to WLED Config Tool: Stability, Flickering, and Visualization + +**Goal:** Address recurring segmentation faults, eliminate LED flickering, and provide a visual ASCII representation of the configured LED layout. + +**Problems Encountered & Solutions:** + +1. **Persistent Segmentation Faults:** + * **Cause:** The interactive layout configuration, initially implemented with a state machine and asynchronous input, suffered from critical memory management issues. Specifically, `QObject` instances (like `WledConfigClient`, `QSocketNotifier`, `WledClient`, `QVector`, `QTimer`) were being created on the heap but were not properly parented to a `QObject` (like `QCoreApplication app`), leading to premature destruction or dangling pointers when accessed from asynchronous callbacks (lambdas). Additionally, `QTextStream` objects were being captured by value in lambdas, making them `const` and preventing non-`const` operations. + * **Resolution:** + * All dynamically allocated `QObject` instances within the interactive configuration were explicitly parented to the `QCoreApplication app` object (`new MyObject(&app)`). This ensures their lifetime is managed by the Qt event loop and they are automatically deleted when the application exits. + * The interactive input logic was simplified. Instead of a complex state machine with asynchronous input for each number, the tool now prompts for all LED counts and the offset upfront using blocking `cin >>` calls. This simplifies the control flow and eliminates the need for complex asynchronous state management during input, making the code more robust. + * `QTextStream` objects (`cin` and `cout`) are now created locally within the `QSocketNotifier::activated` lambda, ensuring they are always valid when used. + +2. **LED Flickering in Interactive Mode:** + * **Cause:** The previous implementation used a `QTimer` to send a full LED data packet every second to keep the WLED device in real-time mode. This constant refreshing, even with identical data, caused a noticeable flicker on the LEDs. + * **Resolution:** + * Research into the WLED UDP Realtime protocol confirmed that the second byte of the DNRGB packet specifies a timeout in seconds. + * The `WledClient::setLedsColor` method was modified to accept a `timeout` parameter. + * In the interactive layout configuration, the LED data is now sent **only once** with a significantly longer timeout (e.g., 60 seconds). This eliminates the need for periodic refresh packets and thus resolves the flickering. The `QTimer` previously used for refreshing was removed. + +3. **ASCII Layout Visualization:** + * **Goal:** Provide a clear, terminal-based visual representation of the configured LED layout. + * **Implementation:** A new function `printAsciiLayout` was added. This function takes the LED counts for each side, the offset, and the total number of LEDs. It generates a rectangular ASCII art representation of the layout using ANSI escape codes to display colored squares (Red for Bottom, Green for Right, Blue for Top, Yellow for Left). This visualization is printed to the console after the LEDs are lit up on the physical device. + +**Outcome:** The `wled_config_tool` is now significantly more stable, the LED flickering issue is resolved, and users can visually confirm their configured layout directly in the terminal. \ No newline at end of file diff --git a/wled_config_tool b/wled_config_tool index 8028b78551e40f7e668574818cb5a5ca055416fd..ea2886bf421fce15cd91300739c38a419ed20476 100755 GIT binary patch literal 88904 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 literal 79016 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 #include #include +#include #include "wledconfigclient.h" #include "wledclient.h" @@ -14,6 +15,7 @@ void runDemoMode(const QString &address, quint16 port, int totalLeds); void runFlashMode(const QString &address, quint16 port, int totalLeds, const QString &flashParams); void delay(int milliseconds); +void printAsciiLayout(int ledsBottom, int ledsRight, int ledsTop, int ledsLeft, int offset, int totalLeds); int main(int argc, char *argv[]) @@ -67,57 +69,89 @@ int main(int argc, char *argv[]) quint16 wledPort = parser.value(portOption).toUShort(); if (parser.isSet(configureLayoutOption)) { - // Interactive LED layout configuration - QTextStream cin(stdin); - QTextStream cout(stdout); + auto configClient = new WledConfigClient(wledAddress, &app); - cout << "Starting interactive LED layout configuration.\n"; - cout.flush(); - cout << "Please enter the number of LEDs for each section.\n"; - cout.flush(); + QObject::connect(configClient, &WledConfigClient::infoReceived, [&](const QJsonObject &info) { + int totalLeds = info["leds"].toObject()["count"].toInt(); + qDebug() << "Your WLED device reports" << totalLeds << "LEDs."; - int ledsToFirstCorner = 0; - cout << "LEDs until the first corner is reached: "; - cout.flush(); - cin >> ledsToFirstCorner; + QTextStream cout(stdout); + QTextStream cin(stdin); - int ledsRightSide = 0; - cout << "LEDs on the right side: "; - cout.flush(); - cin >> ledsRightSide; + cout << "Starting interactive LED layout configuration.\n"; + cout << "Please enter the number of LEDs for each section.\n"; + + int ledsBottom, ledsRight, ledsTop, ledsLeft, offset; - int ledsTop = 0; - cout << "LEDs on the top: "; - cout.flush(); - cin >> ledsTop; + cout << "LEDs on the bottom: "; + cout.flush(); + cin >> ledsBottom; - int ledsLeftSide = 0; - cout << "LEDs on the left side: "; - cout.flush(); - cin >> ledsLeftSide; + cout << "LEDs on the right side: "; + cout.flush(); + cin >> ledsRight; - int ledsBottomRemaining = 0; - cout << "LEDs at the bottom again until the last one is reached: "; - cout.flush(); - cin >> ledsBottomRemaining; + cout << "LEDs on the top: "; + cout.flush(); + cin >> ledsTop; - cout << "\n--- LED Layout Summary ---\n"; - cout.flush(); - cout << "LEDs to first corner: " << ledsToFirstCorner << "\n"; - cout.flush(); - cout << "LEDs on right side: " << ledsRightSide << "\n"; - cout.flush(); - cout << "LEDs on top: " << ledsTop << "\n"; - cout.flush(); - cout << "LEDs on left side: " << ledsLeftSide << "\n"; - cout.flush(); - cout << "LEDs bottom remaining: " << ledsBottomRemaining << "\n"; - cout.flush(); + cout << "LEDs on the left side: "; + cout.flush(); + cin >> ledsLeft; + + cout << "Enter the starting offset (0 if the strip starts at the first LED): "; + cout.flush(); + cin >> offset; - int totalLeds = ledsToFirstCorner + ledsRightSide + ledsTop + ledsLeftSide + ledsBottomRemaining; - cout << "Total LEDs configured: " << totalLeds << "\n"; + int configuredLeds = ledsBottom + ledsRight + ledsTop + ledsLeft; + cout << "Total LEDs configured: " << configuredLeds << "\n"; + cout.flush(); - return 0; // Exit after configuration + if (configuredLeds > totalLeds) { + qWarning() << "Warning: The number of configured LEDs (" << configuredLeds + << ") is greater than the number of LEDs reported by the device (" << totalLeds << ")."; + } + + auto wledClient = new WledClient(wledAddress, wledPort, &app); + auto colors = new QVector(totalLeds, Qt::black); + + int currentIndex = offset; + // Bottom + for (int i = 0; i < ledsBottom; ++i) { (*colors)[(currentIndex + i) % totalLeds] = Qt::red; } + currentIndex += ledsBottom; + // Right + for (int i = 0; i < ledsRight; ++i) { (*colors)[(currentIndex + i) % totalLeds] = Qt::green; } + currentIndex += ledsRight; + // Top + for (int i = 0; i < ledsTop; ++i) { (*colors)[(currentIndex + i) % totalLeds] = Qt::blue; } + currentIndex += ledsTop; + // Left + for (int i = 0; i < ledsLeft; ++i) { (*colors)[(currentIndex + i) % totalLeds] = Qt::yellow; } + + wledClient->setLedsColor(*colors, 60); // Set timeout to 60 seconds + cout << "LEDs have been lit up according to your configuration.\n"; + cout.flush(); + + printAsciiLayout(ledsBottom, ledsRight, ledsTop, ledsLeft, offset, totalLeds); + + cout << "Press Enter to turn off LEDs and exit.\n"; + cout.flush(); + + auto notifier = new QSocketNotifier(fileno(stdin), QSocketNotifier::Read, &app); + QObject::connect(notifier, &QSocketNotifier::activated, [=, &app]() { + colors->fill(Qt::black); + wledClient->setLedsColor(*colors); + app.quit(); + }); + }); + + QObject::connect(configClient, &WledConfigClient::error, [&](const QString &message) { + qCritical() << "Error:" << message; + app.quit(); + }); + + configClient->getInfo(); + return app.exec(); } @@ -166,6 +200,59 @@ int main(int argc, char *argv[]) return app.exec(); } +// ANSI Color Codes +const QString ANSI_RESET = "\033[0m"; +const QString ANSI_RED_BG = "\033[41m"; +const QString ANSI_GREEN_BG = "\033[42m"; +const QString ANSI_BLUE_BG = "\033[44m"; +const QString ANSI_YELLOW_BG = "\033[43m"; + +void printAsciiLayout(int ledsBottom, int ledsRight, int ledsTop, int ledsLeft, int offset, int totalLeds) { + QTextStream cout(stdout); + + int maxHorizontal = qMax(ledsTop, ledsBottom); + int maxVertical = qMax(ledsLeft, ledsRight); + + // Top Row + cout << " "; // Indent for left side + for (int i = 0; i < ledsTop; ++i) { + cout << ANSI_BLUE_BG << " " << ANSI_RESET; // Two spaces for a square + } + cout << "\n"; + + // Middle Rows (Left and Right) + for (int i = 0; i < maxVertical; ++i) { + if (i < ledsLeft) { + cout << ANSI_YELLOW_BG << " " << ANSI_RESET; + } else { + cout << " "; // Empty space if no left LED + } + // Calculate spaces between left and right + int horizontalSpace = maxHorizontal * 2; // Each LED is two chars + cout << QString(horizontalSpace, ' '); + if (i < ledsRight) { + cout << ANSI_GREEN_BG << " " << ANSI_RESET; + } + cout << "\n"; + } + + // Bottom Row + cout << " "; // Indent for left side + for (int i = 0; i < ledsBottom; ++i) { + cout << ANSI_RED_BG << " " << ANSI_RESET; + } + cout << "\n"; + + cout << "\nLayout details:\n"; + cout << " Bottom LEDs (Red): " << ledsBottom << "\n"; + cout << " Right LEDs (Green): " << ledsRight << "\n"; + cout << " Top LEDs (Blue): " << ledsTop << "\n"; + cout << " Left LEDs (Yellow): " << ledsLeft << "\n"; + cout << " Offset: " << offset << "\n"; + cout << " Total LEDs: " << totalLeds << "\n"; + cout.flush(); +} + void runDemoMode(const QString &address, quint16 port, int totalLeds) { qDebug() << "Running demo mode with" << totalLeds << "LEDs on" << address << ":" << port; diff --git a/wledclient.cpp b/wledclient.cpp index 807d496..65d1089 100644 --- a/wledclient.cpp +++ b/wledclient.cpp @@ -77,7 +77,7 @@ void WledClient::sendImage(const QImage &image) } } -void WledClient::setLedsColor(const QVector &colors) +void WledClient::setLedsColor(const QVector &colors, int timeout) { if (colors.isEmpty()) { return; @@ -92,8 +92,8 @@ void WledClient::setLedsColor(const QVector &colors) // Byte 0: Protocol type (DNRGB) datagram.append(DDP_PROTOCOL_DNRGB); - // Byte 1: Timeout (1 second) - datagram.append(1); + // Byte 1: Timeout (in seconds) + datagram.append(timeout); // Bytes 2 & 3: Starting LED index (low byte, then high byte) quint16 startIndex = i; diff --git a/wledclient.h b/wledclient.h index dd0404b..c29b2fa 100644 --- a/wledclient.h +++ b/wledclient.h @@ -15,7 +15,7 @@ public: ~WledClient(); void sendImage(const QImage &image); - void setLedsColor(const QVector &colors); + void setLedsColor(const QVector &colors, int timeout = 1); void flashLeds(int startIndex, int count, QColor color); private: