Patterns for driving rate-limited IoT actuators from real-time producers: async debounced controller, target quantization for stability, and bottom-up progress-bar rendering.
96
96%
Does it follow best practices?
Impact
97%
1.25xAverage score across 9 eval scenarios
Passed
No known issues
Three things a progress bar must do to feel right:
Given total_segments:
lit = int(round(value * total_segments))If hardware has segment 0 at the top (e.g. Govee H6056):
# bottom-up fill: the lit cells are the high indices
segments_to_light = range(total_segments - lit, total_segments)If hardware has segment 0 at the bottom:
segments_to_light = range(0, lit)Two-stop gradient through yellow:
def gradient_rgb(t: float) -> tuple[int, int, int]:
t = max(0.0, min(1.0, t))
if t < 0.5:
return (255, int(255 * (t * 2)), 0) # red -> yellow
return (int(255 * (1 - (t - 0.5) * 2)), 255, 0) # yellow -> greenSee scripts/progress_bar.py for the reference
implementation. Import fill_segments(value, total, top_index_is_zero) and you
cannot get the direction wrong.
fill_segments.for i, seg in enumerate(segments) to light cells in order. That's a top-down fill in disguise.value=0.1 and confirm only the bottom segment lights up. Flip the top_index_is_zero argument if not.debounce-controllerThe target you pass to ctrl.set_target(...) should already be quantised to
int(round(value * total_segments)) — not the raw float. See the
target-quantization skill in this plugin.
debounce-controller — the actuator pattern usually paired with this UI patterntarget-quantization — discrete targets are a prerequisite for debounce stability