Refactor EMA smoothing into composable powermeter wrappers#331
Refactor EMA smoothing into composable powermeter wrappers#331
Conversation
Extract TargetSmoother into SmoothedPowermeter and DeadbandPowermeter wrappers, following the existing decorator pattern. Introduce a PowermeterWrapper base class in a new wrappers/ subfolder to eliminate delegation boilerplate across all five wrappers (transform, throttle, smoother, deadband, pid). The balancer no longer knows about smoothing—it receives pre-smoothed values through the opaque wrapper chain and uses a reset_fn callback for probe commit/reject. Smoothing params (SMOOTH_TARGET_ALPHA, DEADBAND, MAX_SMOOTH_STEP) are now per-powermeter config with [GENERAL] fallback. https://claude.ai/code/session_01LrkYqzhz4EMqBAKG4YAdUR
|
Warning Rate limit exceeded
Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 22 minutes and 31 seconds. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (24)
✨ Finishing Touches🧪 Generate unit tests (beta)
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 |
Remove smooth_target_alpha from CT002 constructor in smoke_efficiency_saturation.py (missed during refactor). Update test_balancer_probe_lockup.py docstring to remove reference to deleted test_smoother.py. https://claude.ai/code/session_01LrkYqzhz4EMqBAKG4YAdUR
Regrouped the flat bullet list into Breaking / Added / Changed / Fixed subsections so readers can scan by change type. Each bullet is now a standalone diff to main (no cross-references) and cites every PR that contributed. Added Breaking entries that were missing: - CT002/CT003 ACTIVE_CONTROL default (smoothing + 15 W BALANCE_DEADBAND + saturation detection on by default) - WAIT_FOR_NEXT_MESSAGE default True (affects Shelly emulation too, not just CT002/CT003) - Async Powermeter base (out-of-tree subclasses must implement async get_powermeter_watts()) Added missing feature bullets: per-powermeter EMA smoothing/deadband wrappers (#331), Hampel outlier filter (#334), MQTT BROKER_URI (#309), exc_info on warnings (#307). Filled in previously-missing PR refs on the rebrand, CT002/CT003, MQTT Insights, web config editor, PID controller, and GIT_COMMIT_SHA bullets. https://claude.ai/code/session_01BCVmemteVXNfoTQE4De2CU
* Restructure CHANGELOG Next section as Keep-a-Changelog diff to main Regrouped the flat bullet list into Breaking / Added / Changed / Fixed subsections so readers can scan by change type. Each bullet is now a standalone diff to main (no cross-references) and cites every PR that contributed. Added Breaking entries that were missing: - CT002/CT003 ACTIVE_CONTROL default (smoothing + 15 W BALANCE_DEADBAND + saturation detection on by default) - WAIT_FOR_NEXT_MESSAGE default True (affects Shelly emulation too, not just CT002/CT003) - Async Powermeter base (out-of-tree subclasses must implement async get_powermeter_watts()) Added missing feature bullets: per-powermeter EMA smoothing/deadband wrappers (#331), Hampel outlier filter (#334), MQTT BROKER_URI (#309), exc_info on warnings (#307). Filled in previously-missing PR refs on the rebrand, CT002/CT003, MQTT Insights, web config editor, PID controller, and GIT_COMMIT_SHA bullets. https://claude.ai/code/session_01BCVmemteVXNfoTQE4De2CU * Fold same-cycle fixes into their parent Added bullets The Fixed / Changed bullets for CT002/CT003 saturation, efficiency- rotation lockup, and the MQTT_INSIGHTS empty-config crash / HA mosquitto availability check referenced features introduced in this same release cycle, so they weren't a standalone diff against main. Merged those PR refs into the CT002/CT003 and MQTT Insights Added bullets (the end state, which is what a main-viewer cares about). Modbus UNIT_ID fix stays in Fixed — Modbus existed on main. https://claude.ai/code/session_01BCVmemteVXNfoTQE4De2CU * Fold CT002/CT003 active-control defaults into Added bullet The CT002/CT003 ACTIVE_CONTROL default is not a 'changed default' vs main — CT002/CT003 don't exist on main, so the default is just part of the new feature description. Moved the default-on behavior and BALANCE_DEADBAND details into the CT002/CT003 Added bullet. Also narrowed the WAIT_FOR_NEXT_MESSAGE Breaking bullet to just the Shelly emulator (the real diff against main); the CT002/CT003 aspect is implicit in the CT002/CT003 Added bullet. Fixed a minor verb mismatch in Changed: 'Added battery activity info logs' → 'Expanded Shelly emulation logs'. https://claude.ai/code/session_01BCVmemteVXNfoTQE4De2CU --------- Co-authored-by: Claude <noreply@anthropic.com>
Summary
Extracted EMA smoothing and deadband gating logic from the monolithic
TargetSmootherclass into composable, reusable powermeter wrapper classes. This enables per-powermeter configuration of smoothing parameters while maintaining the same control-loop semantics.Key Changes
New wrapper architecture: Created
PowermeterWrapperbase class insrc/astrameter/powermeter/wrappers/base.pyto standardize decorator pattern for powermeter compositionExtracted smoothing logic: Split
TargetSmootherinto two focused wrappers:SmoothedPowermeter: Applies exponential moving average (EMA) to total power with sign-change catchup and max-step limitingDeadbandPowermeter: Stateless gate that returns zeros when total power is below thresholdConfiguration flexibility: Updated
config_loader.pyto support per-powermeterSMOOTH_TARGET_ALPHA,MAX_SMOOTH_STEP, andDEADBANDsettings with[GENERAL]section fallbacksSimplified balancer interface: Changed
LoadBalancerto accept optionalreset_fncallback instead of directTargetSmootherreference, decoupling the balancer from smoothing implementationUpdated CT002 integration: Removed embedded smoother from
CT002class; smoothing is now applied at the powermeter layer via config-driven wrapper compositionComprehensive test coverage: Added 243-line test suite (
smoothing_test.py) covering EMA convergence, dedup logic, sign-change catchup, proportional phase distribution, and lifecycle delegationMigrated existing wrappers: Refactored
PidPowermeter,ThrottledPowermeter, andTransformedPowermeterto inherit fromPowermeterWrapperbase classNotable Implementation Details
smooth_target_alpha,max_smooth_step, anddeadbandparameters fromCT002.__init__()in favor of config-driven wrapper compositionhttps://claude.ai/code/session_01LrkYqzhz4EMqBAKG4YAdUR