(POC) Large effect count management#5108
Conversation
Define an "Effect" struct and move the global list out of WS2812FX. The important change is that the id code is now a property of the Effect instead of an index in to a vector. We require retrieving an ID code for an effect to call through a function. This allows us to change the back end implementation of the numeric ID map in the future. Segment::mode is preserved, but marked as deprecated. Usermods not updated yet.
getModeDataSrc() was the API we lost.
Add an endpoint that lists all FX as objects, without any gaps
Move the Effect objects for core effects in to static memory. Saves a little RAM.
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the ✨ Finishing touches🧪 Generate unit tests (beta)
Tip 📝 Customizable high-level summaries are now available in beta!You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.
Example instruction:
Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Pursuant to the ongoing discussions regarding handling large numbers of effects, this spike targets the core API changes I think set the most practical direction for future effect management. The design intent is to preserve compatibility with existing APIs (up to the 255 effect limit), and open a way for new APIs to break that limitation with minimal disruption to existing integrations.
First, the internal upgrade:
The key API changes center around supporting "non-contiguous" effect IDs -- be it names, a paging system, a usermod indexing scheme, or whatever. In all cases, the "effect identifier" is no longer strictly an index in to a vector. To this end, I refactored the effect metadata to a new
struct Effect, keeping all per-effect information (name, function, id) in one place, and built an interface that relies on using functions to look up the Effect entry by name or ID.Internal API changes:
struct Effectto collect effect-related data in one placeclass WS2812FXto newnamespace EffectsEffects::getEffectById()orEffects::getEffectByName(). Function implementations can be replaced or extended to support different indexing approaches (larger id type? numeric ID maps?) without breaking API compatibility.Effect*to look up the function.Segment::modeis preserved for API compatibility, but marked as deprecated.WS2812FX::getModeDataSrc()was the one existing internal API that could not be trivially supported. This impacted one usermod.External API changes:
None. (Or at least none intentionally; I might have missed a special case re "Solid"'s metadata (or lack thereof)). Endpoints 'json/fxda' and 'json/eff' continue to return arrays where the index in to the array matches the 'getEffectById()' callback. Those arrays remain limited to 255 entries to ensure strict compatibility.
From there, the external JSON API is expanded:
{"info": "...", "id": id}, where "id" is only present if the effect id is representable in a uint8_t. This allows an arbitrarily long list of effects to be described to a client without gaps for unused IDs.{"ef": "effect name"}when deserializing a segment, and emits this key when serializing. If "ef" and "fx" are both supplied, "ef" has precedence.The following commit adapts the web UI to use this API instead of ids.
The last commit saves some RAM by moving the Effect objects to code space.
Implementation notes:
strnchr_Pfunction for ESP8266 would be nice.constexpr-transform the existing literals at compile time.namespace Effects. Current implementations of these features in various endpoints work by mutating IDs, which will be problematic if the ID space becomes sparse.Effect*s in a dynamically allocated vector. A future design could also offer a compile-time static list, saving a bit more RAM. The dynamic list could be kept (it's cost is small when empty) for compatibility with older APIs as well as providing a foundation to support runtime-defined effects (ARTI-FX or similar) as fully integrated members.