## Lessons Learned: Hyperion Processor Module

This document captures key insights, challenges, and solutions encountered during the development and testing of the `HyperionProcessor` module.

## 1. Importance of Incremental Testing and Visualization

*   **Challenge:** Initial attempts to debug the `HyperionProcessor`'s output were hampered by a lack of clear visual feedback. Printing raw color values (`#RRGBB`) to the console was not intuitive, and the initial ASCII visualization was difficult to interpret without proper color support or dynamic updates.
*   **Solution:** Breaking down the problem into smaller, verifiable steps proved crucial. First, confirming the `WaylandGrabber` and `HyperionGrabber` were correctly capturing and scaling images (via `QLabel` display) isolated the issue to the processing pipeline. Then, visualizing the *intermediate* step of black border detection (showing the cropped image) provided immediate confirmation of that component's functionality.
*   **Lesson:** For complex image processing or graphical tasks, robust visual debugging tools that show intermediate steps are invaluable. They allow for quick identification and isolation of issues, significantly accelerating the development process.

## 2. Understanding Qt's Logging and Console Output

*   **Challenge:** `qDebug()` and `qInfo()` messages were not appearing in the console during initial `test_hyperion_processor` runs, leading to confusion about whether the code was executing or producing any output.
*   **Solution:** Explicitly configuring `QLoggingCategory::setFilterRules()` and adding `QCoreApplication::processEvents()` calls did not immediately resolve the issue in a simple console application. Ultimately, switching to `std::cout` and `std::cerr` for direct console output bypassed Qt's logging system and guaranteed visibility.
*   **Lesson:** When working with Qt in a console-only context, especially for quick tests, direct `std::cout`/`std::cerr` can be more reliable for immediate feedback than relying solely on Qt's logging framework, which might require more extensive setup for console redirection.

## 3. Robustness of Image Processing to Input Variations

*   **Challenge:** The `HyperionProcessor` initially produced dark, almost black LED colors when tested with `frames/frame_000.png`. This led to initial concerns about the `BlackBorderDetector` or `getAverageColor` logic.

*   **Solution:** Visual inspection of `frame_000.png` revealed it was indeed mostly black. This confirmed that the `HyperionProcessor` was functioning correctly based on its input. The subsequent live testing with `grabberconfigurator` (showing the scaled screen) confirmed the entire capture pipeline was working.
*   **Lesson:** Always validate input data. An unexpected output might not indicate a bug in the processing logic but rather an issue with the input data itself. Using real-world or representative input is critical for accurate testing.

## 4. Iterative Refinement of Visualization

*   **Challenge:** The initial ASCII visualization of LED colors was not clear enough for the user to interpret effectively.
*   **Solution:** Iteratively refining the visualization based on user feedback (e.g., switching from ASCII to `QLabel` for cropped image, then adding thicker outlines and a frame) significantly improved its utility. The ability to dynamically adjust the visualization (e.g., `frameThickness`, `penThickness`) allowed for rapid iteration and better understanding.
*   **Lesson:** User feedback is paramount for effective tool development, especially for visual debugging tools. Start simple, but be prepared to iterate and enhance based on what makes the tool most useful to the end-user.

## 5. Command Line Option Parsing

*   **Challenge:** `QCommandLineOption` definitions using `{"option-name"}` syntax caused parsing errors, leading to options not being recognized and default values being used (e.g., `totalLeds=0`).
*   **Solution:** Explicitly using `QStringList() << "option-name"` for option names resolved the parsing ambiguity.
*   **Lesson:** Pay close attention to framework-specific syntax for command-line argument parsing. Ambiguities can lead to silent failures and incorrect program behavior.

## 6. Pixel Sampling for LED Mapping

*   **Challenge:** Initial `buildLedMap` implementation sampled only a single pixel row/column for each LED, resulting in dark average colors even with vibrant screen content, as screen edges are often dark.
*   **Solution:** Modified `buildLedMap` to sample a *region* of pixels (e.g., 5% of content height/width) for each LED. This provides a more representative average color for the LED's area.
*   **Lesson:** Accurate pixel sampling is crucial for effective Ambilight. Sampling a region rather than a single line provides a more robust and visually appealing color representation, especially for dynamic screen content.

## 7. Debugging `QPainter` Drawing Issues

*   **Challenge:** `QPainter` drawing of filled rectangles and text was not visible, despite `HyperionProcessor` producing correct colors.
*   **Solution:** Isolated drawing of LED regions by temporarily removing the `croppedImage` drawing. This confirmed that the `QPainter` was indeed drawing, but the `croppedImage` was likely covering the drawn elements. The issue was not with the `QPainter` itself, but with the drawing order and the opacity of the `croppedImage`.
*   **Lesson:** When debugging drawing issues, isolate components. Temporarily removing layers or elements can quickly pinpoint where the drawing problem lies. Ensure drawing order and opacity are correctly managed to achieve the desired visual effect.

## 8. External Interference (KWin Script)

*   **Challenge:** Persistent issues with dark LED colors and inconsistent black border detection, despite extensive debugging of the `HyperionProcessor` and `BlackBorderDetector`.
*   **Diagnosis:** The problem was traced to an interfering KWin script (on KDE Plasma Wayland). KWin scripts can overlay or modify screen content in ways that are invisible to screen grabbers, leading to unexpected input images.
*   **Solution:** Disabling the interfering KWin script immediately resolved the issues, allowing the `grabberconfigurator` to display correct and vibrant LED colors.
*   **Lesson:** When debugging screen capture or visual processing issues, always consider external factors like display server configurations, window managers, and overlay applications. These can silently alter the input data, leading to misleading debugging results within the application itself.

## 9. WLED Integration and Testing

*   **Challenge:** Integrating the `WledClient` into `grabberconfigurator` and verifying direct WLED communication.
*   **Solution:** Added `WledClient` instance, command-line options for WLED address/port, and called `setLedsColor` with calculated LED colors. This sets up the pipeline for sending data directly to the WLED device.
*   **Lesson:** Modular design allows for easy integration of different components. The `grabberconfigurator` now serves as a complete testbed for the entire Ambilight pipeline, from screen capture to WLED output.

## 10. Main Application Refactoring and Environment Variable Configuration

*   **Challenge:** Consolidating the screen grabbing, Hyperion processing, and WLED communication into the main `Hyperion_Grabber_Wayland_QT` application and configuring it via environment variables.
*   **Solution:** Refactored `main.cpp` to remove command-line parsing and instead read all configuration parameters (WLED address/port, LED layout, Hyperion algorithm parameters, grabber settings) from environment variables. Implemented a `QTimer` to control the frame processing rate.
*   **Lesson:** Centralizing configuration via environment variables provides flexibility and simplifies deployment. Using a timer for frame processing ensures a consistent update rate for the LEDs, independent of the grabber's frame rate.

[Commit: e31f154] - feat: Implement and verify HyperionProcessor with live visualization
[Commit: 478828b] - docs: Add lesson learned about KWin script interference
[Commit: 60bcfb0] - feat: Integrate WledClient into grabberconfigurator for direct WLED communication
[Commit: c46fade6b0bf71c89c03cbb65d724e98d3db06b4] - feat: Refactor main application for environment variable configuration

## 11. Implementing Configurable Color Order (GRB)

*   **Challenge:** Different LED strips and systems (like WLED) may expect LED color data in various orders (e.g., RGB, GRB, BGR). The initial implementation assumed a fixed RGB order, which led to incorrect color display when connected to devices expecting GRB.
*   **Solution:** Implemented a configurable color order mechanism within the `WledClient` to allow specifying the desired output order (e.g., GRB). This involved remapping the color components (Red, Green, Blue) based on the selected order before sending the data to the WLED device.
*   **Lesson:** When dealing with external hardware or protocols, it's crucial to account for variations in data formats, such as color order. Providing configurable options for such parameters enhances compatibility and flexibility.

[Commit: d81fe64cc10be17f371b43de992be383c8cd7e7f] - feat: Implement GRB color order for WledClient

## 12. Resolving LED Flickering with Increased Frame Rate

*   **Challenge:** LEDs exhibited noticeable flickering when controlled by our Hyperion Grabber, despite the WLED device working flawlessly with other control signals. This suggested an issue within our client's implementation rather than the WLED hardware or configuration.
*   **Diagnosis:** Analysis of real-time LED control protocols (like DDP used by WLED) indicated that timing and update frequency are critical for stable operation. Our application's `processTimer` was set to a very slow 1 frame per second (1000 ms interval), which is insufficient for smooth LED updates and can lead to perceived flickering as LEDs hold old values for too long between updates.
*   **Solution:** Increased the `processTimer` frequency in `main.cpp` from 1000 ms to 33 ms, aiming for approximately 30 frames per second. This significantly improved the update rate of LED colors sent to the WLED device.
*   **Lesson:** For real-time LED control applications, a sufficiently high and consistent frame rate is crucial for preventing flickering and ensuring smooth visual transitions.

[Commit: 6695ca9] - feat: Increase HyperionGrabber frame rate to 30 FPS