Large effect count management #5108
Draft
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.