Kotlin/coroutines patterns for driving rate-limited IoT actuators from real-time producers: debounce controller, target quantization, bottom-up progress-bar rendering.
73
68%
Does it follow best practices?
Impact
95%
1.63xAverage score across 3 eval scenarios
Passed
No known issues
Three patterns for driving rate-limited IoT actuators from real-time producers in Kotlin/coroutines.
debounce-controller-kotlin skill)0.2 s1.2 s — measured ceiling on Govee is ~7 req/min sustained.0.4 s.Dispatchers.IO, NOT Dispatchers.Default. Default is the CPU-bound dispatcher; IO operations starve other CPU work there.target-quantization-kotlin skill)Int 0..6. 3-level semaphore → Int 0..2.Int types for the target. Avoid passing Float/Double through submit().submit() calls for 5 s and count distinct values. If >> the visible-state count, quantise harder.render-progress-bar-kotlin skill)(total - lit) until total.0 until lit.segments.forEachIndexed { i, _ -> if (i < lit) light(i) } — that's top-down fill.io.ktor:ktor-client-cio). Coroutine-friendly out of the box.com.github.ajalt.clikt:clikt) for argument parsing.ch.qos.logback:logback-classic). Structured logging is mandatory for visibility into state transitions and API failures.kotlinx.coroutines with Dispatchers.IO for the controller, Dispatchers.Default only for CPU-bound transforms.runBlocking { client.post(...) } inside the producer loop — blocks the producer at network latency.delay(200) between API calls regardless of transport — 200 ms is wrong for cloud APIs.Dispatchers.Default for HTTP work — IO-bound calls belong on Dispatchers.IO.0.0001 noise blocks every commit.for (i in segments.indices) { if (i < lit) light(i) } — top-down fill, looks like a falling bar.Reference scripts: scripts/DebounceController.kt, scripts/ProgressBar.kt.
Full context in skills/*/SKILL.md.