# FastLED Examples Agent Guidelines ## ๐Ÿšจ CRITICAL: .INO FILE CREATION RULES ### โš ๏ธ THINK BEFORE CREATING .INO FILES โš ๏ธ **.ino files should be created SPARINGLY and ONLY when truly justified.** ### ๐Ÿšซ WHEN NOT TO CREATE .INO FILES: - **Testing minor code changes** - Use existing test files or unit tests - **Quick API validation** - Use unit tests or modify existing examples - **Debugging specific functions** - Use test files, not new sketches - **One-off experiments** - Create temporary test files instead - **Small feature tests** - Extend existing relevant examples ### โœ… WHEN TO CREATE .INO FILES: #### 1. **Temporary Testing (.ino)** **Use Pattern:** `temp_.ino` or `test_.ino` ```cpp // temp_json_api.ino - Testing new JSON fetch functionality // test_networking.ino - Validating network stack changes ``` - โœ… **FOR:** Testing new APIs during development - โœ… **FOR:** Quick prototyping and validation - โœ… **DELETE AFTER USE** - These are temporary by design #### 2. **Significant New Feature Examples** **Use Pattern:** `examples//.ino` ```cpp // examples/JsonFetchApi/JsonFetchApi.ino - Comprehensive JSON API example // examples/NetworkStack/NetworkStack.ino - Major networking features ``` - โœ… **FOR:** Large, comprehensive new features - โœ… **FOR:** APIs that warrant dedicated examples - โœ… **FOR:** Features that users will commonly implement - โœ… **PERMANENT** - These become part of the example library ### ๐Ÿ“‹ CREATION CHECKLIST: **Before creating ANY .ino file, ask:** 1. **๐Ÿค” Is this testing a new API?** - YES โ†’ Create `temp_.ino`, delete after testing - NO โ†’ Consider alternatives 2. **๐Ÿค” Is this a significant new feature that users will commonly use?** - YES โ†’ Create `examples//.ino` - NO โ†’ Use existing examples or test files 3. **๐Ÿค” Can I modify an existing example instead?** - YES โ†’ Extend existing example rather than creating new - NO โ†’ Proceed with creation 4. **๐Ÿค” Is this just for debugging/validation?** - YES โ†’ Use unit tests or temporary test files - NO โ†’ Consider if it meets the "significant feature" criteria ### ๐Ÿ” REVIEW CRITERIA: **For Feature Examples (.ino files that stay):** - โœ… **Demonstrates complete, real-world usage patterns** - โœ… **Covers multiple aspects of the feature comprehensively** - โœ… **Provides educational value for users** - โœ… **Shows best practices and common use cases** - โœ… **Is likely to be referenced by multiple users** **For Temporary Testing (.ino files that get deleted):** - โœ… **Clearly named as temporary (temp_*, test_*)** - โœ… **Focused on specific API validation** - โœ… **Will be deleted after development cycle** - โœ… **Too complex for unit test framework** ### โŒ EXAMPLES OF WHAT NOT TO CREATE: - `test_basic_led.ino` - Use existing Blink example - `debug_colors.ino` - Use existing ColorPalette example - `quick_brightness.ino` - Use unit tests or modify existing example - `validate_pins.ino` - Use PinTest example or unit tests ### โœ… EXAMPLES OF JUSTIFIED CREATIONS: - `temp_new_wifi_api.ino` - Testing major new WiFi functionality (temporary) - `examples/MachineLearning/MachineLearning.ino` - New ML integration feature (permanent) - `temp_performance_test.ino` - Validating optimization changes (temporary) ### ๐Ÿงน CLEANUP RESPONSIBILITY: - **Temporary files:** Creator must delete when testing is complete - **Feature examples:** Must be maintained and updated as API evolves - **Abandoned files:** Regular cleanup reviews to remove unused examples **Remember: The examples directory is user-facing documentation. Every .ino file should provide clear value to FastLED users.** ## Code Standards for Examples ### Use fl:: Namespace (Not std::) **DO NOT use `std::` prefixed functions or headers in examples.** This project provides its own STL-equivalent implementations under the `fl::` namespace. **Examples of what to avoid and use instead:** **Headers:** - โŒ `#include ` โ†’ โœ… `#include "fl/vector.h"` - โŒ `#include ` โ†’ โœ… `#include "fl/string.h"` - โŒ `#include ` โ†’ โœ… `#include "fl/optional.h"` - โŒ `#include ` โ†’ โœ… `#include "fl/scoped_ptr.h"` or `#include "fl/ptr.h"` **Functions and classes:** - โŒ `std::move()` โ†’ โœ… `fl::move()` - โŒ `std::vector` โ†’ โœ… `fl::vector` - โŒ `std::string` โ†’ โœ… `fl::string` **Why:** The project maintains its own implementations to ensure compatibility across all supported platforms and to avoid bloating the library with unnecessary STL dependencies. ### Memory Management **๐Ÿšจ CRITICAL: Always use proper RAII patterns - smart pointers, moveable objects, or wrapper classes instead of raw pointers for resource management.** **Resource Management Options:** - โœ… **PREFERRED**: `fl::shared_ptr` for shared ownership (multiple references to same object) - โœ… **PREFERRED**: `fl::unique_ptr` for exclusive ownership (single owner, automatic cleanup) - โœ… **PREFERRED**: Moveable wrapper objects (like `fl::promise`) for safe copying and transferring of unique resources - โœ… **ACCEPTABLE**: `fl::vector` storing objects by value when objects support move/copy semantics - โŒ **AVOID**: `fl::vector` storing raw pointers - use `fl::vector>` or `fl::vector>` - โŒ **AVOID**: Manual `new`/`delete` - use `fl::make_shared()` or `fl::make_unique()` **Examples:** ```cpp // โœ… GOOD - Using smart pointers fl::vector> mActiveClients; auto client = fl::make_shared(); mActiveClients.push_back(client); // โœ… GOOD - Using unique_ptr for exclusive ownership fl::unique_ptr client = fl::make_unique(); // โœ… GOOD - Moveable wrapper objects (fl::promise example) fl::vector> mActivePromises; // Copyable wrapper around unique future fl::promise promise = fetch.get(url).execute(); mActivePromises.push_back(promise); // Safe copy, shared internal state // โŒ BAD - Raw pointers require manual memory management fl::vector mActivePromises; // Memory leaks possible Promise* promise = new Promise(); // Who calls delete? ``` ### Debug Printing **Use `FL_WARN` for debug printing in examples.** This ensures consistent debug output that works in both unit tests and live application testing. **Usage:** - โœ… `FL_WARN("Debug message: " << message);` - โŒ `FL_WARN("Value: %d", value);` ### No Emoticons or Emojis **NO emoticons or emoji characters are allowed in C++ source files.** This ensures professional, maintainable code that works correctly across all platforms and development environments. **Examples of what NOT to do in .ino files:** ```cpp // โŒ BAD - Emoticons in comments // ๐ŸŽฏ This function handles user input // โŒ BAD - Emoticons in log messages FL_WARN("โœ… Operation successful!"); FL_WARN("โŒ Error occurred: " << error_msg); // โŒ BAD - Emoticons in string literals const char* status = "๐Ÿ”„ Processing..."; ``` **Examples of correct alternatives:** ```cpp // โœ… GOOD - Clear text in comments // TUTORIAL: This function handles user input // โœ… GOOD - Text prefixes in log messages FL_WARN("SUCCESS: Operation completed successfully!"); FL_WARN("ERROR: Failed to process request: " << error_msg); // โœ… GOOD - Descriptive text in string literals const char* status = "PROCESSING: Request in progress..."; ``` ### JSON Usage - Ideal API Patterns **๐ŸŽฏ PREFERRED: Use the modern `fl::Json` class for all JSON operations.** FastLED provides an ideal JSON API that prioritizes type safety, ergonomics, and crash-proof operation. **โœ… IDIOMATIC JSON USAGE:** ```cpp // NEW: Clean, safe, idiomatic API fl::Json json = fl::Json::parse(jsonStr); int brightness = json["config"]["brightness"] | 128; // Gets value or 128 default string name = json["device"]["name"] | string("default"); // Type-safe with default bool enabled = json["features"]["networking"] | false; // Never crashes // Array operations if (json["effects"].contains("rainbow")) { // Safe array checking } ``` **โŒ DISCOURAGED: Verbose legacy API:** ```cpp // OLD: Verbose, error-prone API (still works, but not recommended) fl::JsonDocument doc; fl::string error; fl::parseJson(jsonStr, &doc, &error); int brightness = doc["config"]["brightness"].as(); // Can crash if missing ``` **๐Ÿ“š Reference Example:** See `examples/Json/Json.ino` for comprehensive usage patterns and API comparison. ## Example Compilation Commands ### Platform Compilation ```bash # Compile examples for specific platforms uv run ci/ci-compile.py uno --examples Blink uv run ci/ci-compile.py esp32dev --examples Blink uv run ci/ci-compile.py teensy31 --examples Blink bash compile uno --examples Blink ``` ### WASM Compilation **๐ŸŽฏ HOW TO COMPILE ANY ARDUINO SKETCH TO WASM:** **Basic Compilation Commands:** ```bash # Compile any sketch directory to WASM uv run ci/wasm_compile.py path/to/your/sketch # Quick compile test (compile only, no browser) uv run ci/wasm_compile.py path/to/your/sketch --just-compile # Compile examples/Blink to WASM uv run ci/wasm_compile.py examples/Blink --just-compile # Compile examples/NetTest to WASM (test fetch API) uv run ci/wasm_compile.py examples/NetTest --just-compile # Compile examples/DemoReel100 to WASM uv run ci/wasm_compile.py examples/DemoReel100 --just-compile ``` **Output:** Creates `fastled_js/` folder with: - `fastled.js` - JavaScript loader - `fastled.wasm` - WebAssembly binary - `index.html` - HTML page to run the sketch **Run in Browser:** ```bash # Simple HTTP server to test cd fastled_js python -m http.server 8000 # Open http://localhost:8000 ``` **๐Ÿšจ REQUIREMENTS:** - **Docker must be installed and running** - **Internet connection** (for Docker image download on first run) - **~1GB RAM** for Docker container during compilation ### WASM Testing Requirements **๐Ÿšจ MANDATORY: Always test WASM compilation after platform file changes** **Platform Testing Commands:** ```bash # Test WASM platform changes (for platform developers) uv run ci/wasm_compile.py examples/wasm --just-compile # Quick compile test for any sketch (compile only, no browser) uv run ci/wasm_compile.py examples/Blink --just-compile # Quick compile test for NetTest example uv run ci/wasm_compile.py examples/NetTest --just-compile # Quick test without full build uv run ci/wasm_compile.py examples/wasm --quick ``` **Watch For These Error Patterns:** - `error: conflicting types for 'function_name'` - `error: redefinition of 'function_name'` - `warning: attribute declaration must precede definition` - `RuntimeError: unreachable` (often async-related) **MANDATORY RULES:** - **ALWAYS test WASM compilation** after modifying any WASM platform files - **USE `uv run ci/wasm_compile.py` for validation** - **WATCH for unified build conflicts** in compilation output - **VERIFY async operations work properly** in browser environment ## Compiler Warning Suppression **ALWAYS use the FastLED compiler control macros from `fl/compiler_control.h` for warning suppression.** This ensures consistent cross-compiler support and proper handling of platform differences. **Correct Warning Suppression Pattern:** ```cpp #include "fl/compiler_control.h" // Suppress specific warning around problematic code FL_DISABLE_WARNING_PUSH FL_DISABLE_FORMAT_TRUNCATION // Use specific warning macros // ... code that triggers warnings ... FL_DISABLE_WARNING_POP ``` **Available Warning Suppression Macros:** - โœ… `FL_DISABLE_WARNING_PUSH` / `FL_DISABLE_WARNING_POP` - Standard push/pop pattern - โœ… `FL_DISABLE_WARNING(warning_name)` - Generic warning suppression (use sparingly) - โœ… `FL_DISABLE_WARNING_GLOBAL_CONSTRUCTORS` - Clang global constructor warnings - โœ… `FL_DISABLE_WARNING_SELF_ASSIGN_OVERLOADED` - Clang self-assignment warnings - โœ… `FL_DISABLE_FORMAT_TRUNCATION` - GCC format truncation warnings **What NOT to do:** - โŒ **NEVER use raw `#pragma` directives** - they don't handle compiler differences - โŒ **NEVER write manual `#ifdef __clang__` / `#ifdef __GNUC__` blocks** - use the macros - โŒ **NEVER ignore warnings without suppression** - fix the issue or suppress appropriately ## Exception Handling **DO NOT use try-catch blocks or C++ exception handling in examples.** FastLED is designed to work on embedded systems like Arduino where exception handling may not be available or desired due to memory and performance constraints. **Use Error Handling Alternatives:** - โœ… **Return error codes:** `bool function() { return false; }` or custom error enums - โœ… **Optional types:** `fl::optional` for functions that may not return a value - โœ… **Assertions:** `FL_ASSERT(condition)` for debug-time validation - โœ… **Early returns:** `if (!valid) return false;` for error conditions - โœ… **Status objects:** Custom result types that combine success/failure with data **Examples of proper error handling:** ```cpp // Good: Using return codes bool initializeHardware() { if (!setupPins()) { FL_WARN("Failed to setup pins"); return false; } return true; } // Good: Using fl::optional fl::optional calculateValue(int input) { if (input < 0) { return fl::nullopt; // No value, indicates error } return fl::make_optional(sqrt(input)); } // Good: Using early returns void processData(const uint8_t* data, size_t len) { if (!data || len == 0) { FL_WARN("Invalid input data"); return; // Early return on error } // Process data... } ``` ## Memory Refresh Rule **๐Ÿšจ ALL AGENTS: Read examples/AGENTS.md before concluding example work to refresh memory about .ino file creation rules and example coding standards.**