Skip to content

Fix HTTP-polled meter configs truncating large JSON responses#535

Open
tomquist wants to merge 6 commits into
developfrom
claude/astrameter-discussion-534-2ts777
Open

Fix HTTP-polled meter configs truncating large JSON responses#535
tomquist wants to merge 6 commits into
developfrom
claude/astrameter-discussion-534-2ts777

Conversation

@tomquist

@tomquist tomquist commented Jun 30, 2026

Copy link
Copy Markdown
Owner

Summary

ESPHome's default HTTP receive buffer is too small for large JSON responses from meters like the Fronius Solar API, causing the response body to be truncated and json::parse_json to silently fail. This fix enlarges the buffer on both the HTTP client and per-request action so generated configs work without manual editing.

Changes

  • Generator (web/ts/generate.ts):

    • Added buffer_size_rx: 4096 to the http_request: block
    • Added max_response_buffer_size: 4096 to the per-request http_request.get: action
    • Documented the issue with a comment explaining why the buffer must be enlarged
  • Documentation (docs/esphome-powermeters.md):

    • Updated the Fronius Smart Meter example config to include both buffer size settings
    • Added explanation of why these settings are required
  • Tests (web/ts/generate.test.ts):

    • Added assertions verifying both buffer size settings appear in generated configs
    • Added comment explaining the issue and referencing the discussion
  • Changelog (CHANGELOG.md):

    • Added user-facing entry documenting the fix for HTTP-polled meters

Implementation Details

The fix uses a constant RX_BUFFER = 4096 to ensure both buffer settings use the same value. This size accommodates the multi-KB JSON responses from the Fronius Solar API while remaining reasonable for embedded systems.

https://claude.ai/code/session_01FEzZ7zoMfEEZt2cyrdiAV4

Summary by CodeRabbit

  • Bug Fixes
    • Improved generated ESPHome HTTP polling settings for large JSON responses, preventing failed grid readings and related control issues; also avoids duplicate HTTP request blocks and ensures the intended timeout is applied when needed.
  • Documentation
    • Updated the power meter setup guide with clearer configuration guidance and buffer sizing notes for APIs that return multi‑KB payloads.
  • Tests
    • Expanded generator coverage to verify increased HTTP receive/response buffers and correct merged http_request behavior.

tomquist and others added 2 commits June 30, 2026 04:58
The Fronius Solar API (and other verbose HTTP meters) return a multi-KB
JSON document, but the generated config left ESPHome's small default
receive buffer in place, so the body was truncated and json::parse_json
silently failed. The grid reading stayed stuck and the battery went
uncontrolled until users manually enlarged the buffer (discussion #534).

Emit buffer_size_rx on http_request and max_response_buffer_size on the
per-request action (4 KB) so the config works as generated. Update the
Fronius ESPHome doc example and add a changelog entry.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FEzZ7zoMfEEZt2cyrdiAV4
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FEzZ7zoMfEEZt2cyrdiAV4
@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5cf0e454-4d0e-4a00-b438-dbf424868d52

📥 Commits

Reviewing files that changed from the base of the PR and between d4ef1b4 and a032c2b.

📒 Files selected for processing (2)
  • web/ts/generate.test.ts
  • web/ts/generate.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • web/ts/generate.test.ts

Walkthrough

The ESPHome generator now emits larger HTTP buffers for JSON polling and reuses existing http_request blocks when adding a 20s timeout. Matching docs, tests, changelog text, and changelog-writing guidance were updated.

Changes

ESPHome HTTP buffer and timeout generation

Layer / File(s) Summary
Generator buffer settings
web/ts/generate.ts
Adds RX_BUFFER, emits buffer_size_rx on the HTTP meter request, and sets max_response_buffer_size for the polling action.
Generator timeout merge
web/ts/generate.ts, web/ts/generate.test.ts
Reuses an existing top-level http_request block when cloud_reporting or marstek_registration is enabled, and tests assert the merged timeout and retained buffer output.
Docs, changelog, and guidance
docs/esphome-powermeters.md, CHANGELOG.md, AGENTS.md
Updates the Fronius example and note, adds the changelog fixed entry, and tightens the changelog bullet guidance.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main fix for HTTP-polled meter configs truncating large JSON responses.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/astrameter-discussion-534-2ts777

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FEzZ7zoMfEEZt2cyrdiAV4
@github-actions

Copy link
Copy Markdown
Contributor

🚀 Preview for this PR is deployed at
https://astrameter.com/pr-preview/pr-535/

It will be live once the GitHub Pages deployment finishes.

@tomquist tomquist marked this pull request as ready for review June 30, 2026 05:06
@github-actions

github-actions Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Steering evaluation (base vs head)

Overall: 0 improved, 0 regressed, 15 unchanged across 15 metrics — mean 0% (unchanged).

Priority: priority-weighted 0% (unchanged) — ✅ no do-no-harm guardrail regressions.

Lower is better for every metric. See src/astrameter/simulator/evaluation.py for definitions.

Metrics are the per-scenario mean of 5 seeds.

Aggregate — mean across 32 scenarios

Metric Base Head Δ
settle_mean_s 35.2 35.2 =
settle_p95_s 61.6 61.6 =
unsettled_events 0.5 0.5 =
overshoot_mean_w 44.0 44.0 =
overshoot_max_w 94.6 94.6 =
band_crossings_per_h 297.2 297.2 =
grid_p2p_w 257.8 257.8 =
grid_rms_w 239.5 239.5 =
steady_rms_w 111.6 111.6 =
mean_abs_grid_w 95.2 95.2 =
share_imbalance_w 60.8 60.8 =
avoidable_import_wh 35.0 35.0 =
avoidable_export_wh 25.5 25.5 =
cost_regret_ct 0.82 0.82 =
battery_travel_w_per_h 23700.4 23700.4 =

📊 Interactive grid-power charts (zoom / hover / toggle series) are in the self-contained steering-eval-report.html report — see the link below (it opens directly in the browser).

What do these metrics mean?
Metric Meaning
settle_mean_s Mean seconds after a load/PV step for grid power to return inside the ±25 W settle band and hold for 10 s (reaction speed).
settle_p95_s 95th-percentile settle time — the slow tail of reactions.
unsettled_events Number of disturbance events that never settled within the 10-minute measurement window.
overshoot_mean_w Mean overshoot (W): how far grid power swings past zero to the opposite sign after an event.
overshoot_max_w Worst-case overshoot (W) across all events.
band_crossings_per_h Sign flips per hour across the ±20 W hysteresis band — oscillation / hunting frequency.
grid_p2p_w Sustained peak-to-peak grid swing (95th - 5th percentile) over the whole run — oscillation amplitude. Non-zero whenever the loop keeps hunting, including continuous oscillation the step-response metrics (settle/overshoot) miss.
grid_rms_w RMS grid power (W) over the whole run, transients included — the L2 tracking error: how cleanly the loop held zero, penalising big excursions (overshoot, swings) far harder than a small steady offset. Pairs with battery_travel_w_per_h as the control-effort term.
steady_rms_w RMS grid power (W) during steady state (excluding the 120 s after each event) — residual jitter when nothing is changing.
mean_abs_grid_w Mean absolute grid power (W) over the whole run — overall tracking accuracy.
share_imbalance_w Time-weighted watts misallocated between batteries sharing a phase (sum of each battery's deviation from the even fair share) — 0 when the pool splits load evenly, higher when one battery is left lopsided (issue #523). 0 for scenarios with at most one battery per phase.
avoidable_import_wh Energy imported from the grid (Wh) the battery could have supplied (it had charge and discharge headroom) — missed self-consumption.
avoidable_export_wh Energy exported to the grid (Wh) an AC-chargeable battery could have absorbed (it had room and charge headroom) — missed charging.
cost_regret_ct Money north-star: electricity bill (eurocents, import @ 30 ct/kWh, export @ 8 ct/kWh) over what a perfect-foresight optimal battery would have paid on the same load. Ungameable (both grid directions cost); 0 = matched the optimum. The single number that says how much the controller left on the table.
battery_travel_w_per_h Total absolute change in battery setpoints per hour (W/h) — control effort / actuator wear; lower is smoother.
Per-scenario tables (32 scenarios)
full_battery_low_pace — settle 0.0→0.0s, overshoot 0.0→0.0W, RMS 29.1→29.1W
Metric Base Head Δ
settle_mean_s 0.0 0.0 =
settle_p95_s 0.0 0.0 =
unsettled_events 0.0 0.0 =
overshoot_mean_w 0.0 0.0 =
overshoot_max_w 0.0 0.0 =
band_crossings_per_h 0.0 0.0 =
grid_p2p_w 70.0 70.0 =
grid_rms_w 29.1 29.1 =
steady_rms_w 29.1 29.1 =
mean_abs_grid_w 14.5 14.5 =
share_imbalance_w 0.0 0.0 =
avoidable_import_wh 0.0 0.0 =
avoidable_export_wh 3.6 3.6 =
cost_regret_ct 0.0 0.0 =
battery_travel_w_per_h 31900.0 31900.0 =
mixed_cadence/eff — settle 50.8→50.8s, overshoot 164.5→164.5W, RMS 21.9→21.9W
Metric Base Head Δ
settle_mean_s 50.8 50.8 =
settle_p95_s 72.4 72.4 =
unsettled_events 0.0 0.0 =
overshoot_mean_w 64.0 64.0 =
overshoot_max_w 164.5 164.5 =
band_crossings_per_h 24.4 24.4 =
grid_p2p_w 160.6 160.6 =
grid_rms_w 255.3 255.3 =
steady_rms_w 21.9 21.9 =
mean_abs_grid_w 64.1 64.1 =
share_imbalance_w 223.0 223.0 =
avoidable_import_wh 38.5 38.5 =
avoidable_export_wh 25.6 25.6 =
cost_regret_ct 0.95 0.95 =
battery_travel_w_per_h 31306.0 31306.0 =
mixed_cadence/fair — settle 47.7→47.7s, overshoot 70.4→70.4W, RMS 12.9→12.9W
Metric Base Head Δ
settle_mean_s 47.7 47.7 =
settle_p95_s 67.4 67.4 =
unsettled_events 0.0 0.0 =
overshoot_mean_w 30.7 30.7 =
overshoot_max_w 70.4 70.4 =
band_crossings_per_h 21.6 21.6 =
grid_p2p_w 131.9 131.9 =
grid_rms_w 246.0 246.0 =
steady_rms_w 12.9 12.9 =
mean_abs_grid_w 58.6 58.6 =
share_imbalance_w 101.3 101.3 =
avoidable_import_wh 33.7 33.7 =
avoidable_export_wh 24.9 24.9 =
cost_regret_ct 0.81 0.81 =
battery_travel_w_per_h 28457.4 28457.4 =
mixed_cadence_solar/eff — settle 52.5→52.5s, overshoot 384.7→384.7W, RMS 28.6→28.6W
Metric Base Head Δ
settle_mean_s 52.5 52.5 =
settle_p95_s 95.6 95.6 =
unsettled_events 2.0 2.0 =
overshoot_mean_w 62.4 62.4 =
overshoot_max_w 384.7 384.7 =
band_crossings_per_h 37.3 37.3 =
grid_p2p_w 192.3 192.3 =
grid_rms_w 268.4 268.4 =
steady_rms_w 28.6 28.6 =
mean_abs_grid_w 76.4 76.4 =
share_imbalance_w 148.1 148.1 =
avoidable_import_wh 60.5 60.5 =
avoidable_export_wh 54.1 54.1 =
cost_regret_ct 1.38 1.38 =
battery_travel_w_per_h 37319.8 37319.8 =
mixed_cadence_solar/fair — settle 56.0→56.0s, overshoot 75.4→75.4W, RMS 23.7→23.7W
Metric Base Head Δ
settle_mean_s 56.0 56.0 =
settle_p95_s 119.5 119.5 =
unsettled_events 1.8 1.8 =
overshoot_mean_w 28.7 28.7 =
overshoot_max_w 75.4 75.4 =
band_crossings_per_h 28.3 28.3 =
grid_p2p_w 147.8 147.8 =
grid_rms_w 261.6 261.6 =
steady_rms_w 23.7 23.7 =
mean_abs_grid_w 72.2 72.2 =
share_imbalance_w 119.0 119.0 =
avoidable_import_wh 56.0 56.0 =
avoidable_export_wh 52.4 52.4 =
cost_regret_ct 1.26 1.26 =
battery_travel_w_per_h 32435.8 32435.8 =
mixed_venus_b2500/eff — settle 81.2→81.2s, overshoot 221.9→221.9W, RMS 18.6→18.6W
Metric Base Head Δ
settle_mean_s 81.2 81.2 =
settle_p95_s 217.1 217.1 =
unsettled_events 2.4 2.4 =
overshoot_mean_w 100.2 100.2 =
overshoot_max_w 221.9 221.9 =
band_crossings_per_h 49.2 49.2 =
grid_p2p_w 67.3 67.3 =
grid_rms_w 197.5 197.5 =
steady_rms_w 18.6 18.6 =
mean_abs_grid_w 43.2 43.2 =
share_imbalance_w 263.0 263.0 =
avoidable_import_wh 44.2 44.2 =
avoidable_export_wh 20.5 20.5 =
cost_regret_ct 1.16 1.16 =
battery_travel_w_per_h 39704.6 39704.6 =
mixed_venus_b2500/fair — settle 75.4→75.4s, overshoot 231.1→231.1W, RMS 22.3→22.3W
Metric Base Head Δ
settle_mean_s 75.4 75.4 =
settle_p95_s 191.0 191.0 =
unsettled_events 1.4 1.4 =
overshoot_mean_w 110.5 110.5 =
overshoot_max_w 231.1 231.1 =
band_crossings_per_h 53.3 53.3 =
grid_p2p_w 67.1 67.1 =
grid_rms_w 189.9 189.9 =
steady_rms_w 22.3 22.3 =
mean_abs_grid_w 44.5 44.5 =
share_imbalance_w 100.7 100.7 =
avoidable_import_wh 47.4 47.4 =
avoidable_export_wh 19.4 19.4 =
cost_regret_ct 1.27 1.27 =
battery_travel_w_per_h 43475.4 43475.4 =
phase_imbalance — settle 53.4→53.4s, overshoot 145.2→145.2W, RMS 30.3→30.3W
Metric Base Head Δ
settle_mean_s 53.4 53.4 =
settle_p95_s 123.6 123.6 =
unsettled_events 0.0 0.0 =
overshoot_mean_w 64.9 64.9 =
overshoot_max_w 145.2 145.2 =
band_crossings_per_h 87.6 87.6 =
grid_p2p_w 42.4 42.4 =
grid_rms_w 199.6 199.6 =
steady_rms_w 30.3 30.3 =
mean_abs_grid_w 40.4 40.4 =
share_imbalance_w 0.0 0.0 =
avoidable_import_wh 25.6 25.6 =
avoidable_export_wh 14.8 14.8 =
cost_regret_ct 0.65 0.65 =
battery_travel_w_per_h 18274.2 18274.2 =
single_venus_d_solar — settle 24.2→24.2s, overshoot 94.4→94.4W, RMS 15.9→15.9W
Metric Base Head Δ
settle_mean_s 24.2 24.2 =
settle_p95_s 27.1 27.1 =
unsettled_events 0.0 0.0 =
overshoot_mean_w 76.8 76.8 =
overshoot_max_w 94.4 94.4 =
band_crossings_per_h 10.7 10.7 =
grid_p2p_w 29.9 29.9 =
grid_rms_w 104.3 104.3 =
steady_rms_w 15.9 15.9 =
mean_abs_grid_w 18.5 18.5 =
share_imbalance_w 0.0 0.0 =
avoidable_import_wh 17.9 17.9 =
avoidable_export_wh 9.9 9.9 =
cost_regret_ct 0.46 0.46 =
battery_travel_w_per_h 9425.4 9425.4 =
single_venus_d_steps — settle 26.3→26.3s, overshoot 90.3→90.3W, RMS 15.5→15.5W
Metric Base Head Δ
settle_mean_s 26.3 26.3 =
settle_p95_s 33.8 33.8 =
unsettled_events 0.0 0.0 =
overshoot_mean_w 73.3 73.3 =
overshoot_max_w 90.3 90.3 =
band_crossings_per_h 25.8 25.8 =
grid_p2p_w 30.9 30.9 =
grid_rms_w 256.4 256.4 =
steady_rms_w 15.5 15.5 =
mean_abs_grid_w 58.6 58.6 =
share_imbalance_w 0.0 0.0 =
avoidable_import_wh 32.3 32.3 =
avoidable_export_wh 26.2 26.2 =
cost_regret_ct 0.76 0.76 =
battery_travel_w_per_h 21425.2 21425.2 =
single_venus_d_washer — settle 0.0→0.0s, overshoot 0.0→0.0W, RMS 61.0→61.0W
Metric Base Head Δ
settle_mean_s 0.0 0.0 =
settle_p95_s 0.0 0.0 =
unsettled_events 0.0 0.0 =
overshoot_mean_w 0.0 0.0 =
overshoot_max_w 0.0 0.0 =
band_crossings_per_h 322.4 322.4 =
grid_p2p_w 192.7 192.7 =
grid_rms_w 61.0 61.0 =
steady_rms_w 61.0 61.0 =
mean_abs_grid_w 42.8 42.8 =
share_imbalance_w 0.0 0.0 =
avoidable_import_wh 13.3 13.3 =
avoidable_export_wh 8.1 8.1 =
cost_regret_ct 0.33 0.33 =
battery_travel_w_per_h 24204.4 24204.4 =
single_venus_drain — settle 0.0→0.0s, overshoot 0.0→0.0W, RMS 907.3→907.3W
Metric Base Head Δ
settle_mean_s 0.0 0.0 =
settle_p95_s 0.0 0.0 =
unsettled_events 0.0 0.0 =
overshoot_mean_w 0.0 0.0 =
overshoot_max_w 0.0 0.0 =
band_crossings_per_h 73.2 73.2 =
grid_p2p_w 1598.9 1598.9 =
grid_rms_w 907.3 907.3 =
steady_rms_w 907.3 907.3 =
mean_abs_grid_w 645.3 645.3 =
share_imbalance_w 0.0 0.0 =
avoidable_import_wh 14.4 14.4 =
avoidable_export_wh 10.2 10.2 =
cost_regret_ct 0.21 0.21 =
battery_travel_w_per_h 4062.0 4062.0 =
single_venus_fill — settle 360.0→360.0s, overshoot 0.0→0.0W, RMS 953.6→953.6W
Metric Base Head Δ
settle_mean_s 360.0 360.0 =
settle_p95_s 600.0 600.0 =
unsettled_events 4.0 4.0 =
overshoot_mean_w 0.0 0.0 =
overshoot_max_w 0.0 0.0 =
band_crossings_per_h 10.1 10.1 =
grid_p2p_w 1713.1 1713.1 =
grid_rms_w 978.6 978.6 =
steady_rms_w 953.6 953.6 =
mean_abs_grid_w 662.8 662.8 =
share_imbalance_w 0.0 0.0 =
avoidable_import_wh 4.8 4.8 =
avoidable_export_wh 6.7 6.7 =
cost_regret_ct 0.14 0.14 =
battery_travel_w_per_h 3173.0 3173.0 =
single_venus_noisy — settle 0.0→0.0s, overshoot 0.0→0.0W, RMS 94.3→94.3W
Metric Base Head Δ
settle_mean_s 0.0 0.0 =
settle_p95_s 0.0 0.0 =
unsettled_events 0.0 0.0 =
overshoot_mean_w 0.0 0.0 =
overshoot_max_w 0.0 0.0 =
band_crossings_per_h 1452.6 1452.6 =
grid_p2p_w 296.7 296.7 =
grid_rms_w 94.3 94.3 =
steady_rms_w 94.3 94.3 =
mean_abs_grid_w 79.1 79.1 =
share_imbalance_w 0.0 0.0 =
avoidable_import_wh 42.0 42.0 =
avoidable_export_wh 37.0 37.0 =
cost_regret_ct 0.96 0.96 =
battery_travel_w_per_h 22758.8 22758.8 =
single_venus_pv — settle 0.0→0.0s, overshoot 0.0→0.0W, RMS 60.8→60.8W
Metric Base Head Δ
settle_mean_s 0.0 0.0 =
settle_p95_s 0.0 0.0 =
unsettled_events 0.0 0.0 =
overshoot_mean_w 0.0 0.0 =
overshoot_max_w 0.0 0.0 =
band_crossings_per_h 38.5 38.5 =
grid_p2p_w 42.9 42.9 =
grid_rms_w 60.8 60.8 =
steady_rms_w 60.8 60.8 =
mean_abs_grid_w 17.3 17.3 =
share_imbalance_w 0.0 0.0 =
avoidable_import_wh 9.9 9.9 =
avoidable_export_wh 16.1 16.1 =
cost_regret_ct 0.17 0.17 =
battery_travel_w_per_h 6782.0 6782.0 =
single_venus_solar — settle 26.8→26.8s, overshoot 80.3→80.3W, RMS 17.8→17.8W
Metric Base Head Δ
settle_mean_s 26.8 26.8 =
settle_p95_s 32.6 32.6 =
unsettled_events 0.0 0.0 =
overshoot_mean_w 67.1 67.1 =
overshoot_max_w 80.3 80.3 =
band_crossings_per_h 26.3 26.3 =
grid_p2p_w 41.9 41.9 =
grid_rms_w 108.7 108.7 =
steady_rms_w 17.8 17.8 =
mean_abs_grid_w 21.2 21.2 =
share_imbalance_w 0.0 0.0 =
avoidable_import_wh 15.5 15.5 =
avoidable_export_wh 16.3 16.3 =
cost_regret_ct 0.34 0.34 =
battery_travel_w_per_h 7331.6 7331.6 =
single_venus_solar_slow — settle 33.9→33.9s, overshoot 68.3→68.3W, RMS 22.8→22.8W
Metric Base Head Δ
settle_mean_s 33.9 33.9 =
settle_p95_s 39.9 39.9 =
unsettled_events 0.0 0.0 =
overshoot_mean_w 32.1 32.1 =
overshoot_max_w 68.3 68.3 =
band_crossings_per_h 5.6 5.6 =
grid_p2p_w 60.6 60.6 =
grid_rms_w 131.7 131.7 =
steady_rms_w 22.8 22.8 =
mean_abs_grid_w 31.6 31.6 =
share_imbalance_w 0.0 0.0 =
avoidable_import_wh 21.3 21.3 =
avoidable_export_wh 26.1 26.1 =
cost_regret_ct 0.43 0.43 =
battery_travel_w_per_h 6486.0 6486.0 =
single_venus_steps — settle 26.0→26.0s, overshoot 88.0→88.0W, RMS 14.7→14.7W
Metric Base Head Δ
settle_mean_s 26.0 26.0 =
settle_p95_s 32.7 32.7 =
unsettled_events 0.0 0.0 =
overshoot_mean_w 69.7 69.7 =
overshoot_max_w 88.0 88.0 =
band_crossings_per_h 23.8 23.8 =
grid_p2p_w 27.1 27.1 =
grid_rms_w 266.9 266.9 =
steady_rms_w 14.7 14.7 =
mean_abs_grid_w 61.1 61.1 =
share_imbalance_w 0.0 0.0 =
avoidable_import_wh 34.1 34.1 =
avoidable_export_wh 27.0 27.0 =
cost_regret_ct 0.8 0.8 =
battery_travel_w_per_h 19543.6 19543.6 =
single_venus_steps_slow — settle 40.5→40.5s, overshoot 98.5→98.5W, RMS 14.8→14.8W
Metric Base Head Δ
settle_mean_s 40.5 40.5 =
settle_p95_s 56.2 56.2 =
unsettled_events 0.0 0.0 =
overshoot_mean_w 37.1 37.1 =
overshoot_max_w 98.5 98.5 =
band_crossings_per_h 9.4 9.4 =
grid_p2p_w 78.2 78.2 =
grid_rms_w 331.7 331.7 =
steady_rms_w 14.8 14.8 =
mean_abs_grid_w 88.2 88.2 =
share_imbalance_w 0.0 0.0 =
avoidable_import_wh 47.5 47.5 =
avoidable_export_wh 40.7 40.7 =
cost_regret_ct 1.1 1.1 =
battery_travel_w_per_h 17699.8 17699.8 =
single_venus_trace — settle 0.0→0.0s, overshoot 0.0→0.0W, RMS 278.9→278.9W
Metric Base Head Δ
settle_mean_s 0.0 0.0 =
settle_p95_s 0.0 0.0 =
unsettled_events 0.0 0.0 =
overshoot_mean_w 0.0 0.0 =
overshoot_max_w 0.0 0.0 =
band_crossings_per_h 284.8 284.8 =
grid_p2p_w 689.3 689.3 =
grid_rms_w 278.5 278.5 =
steady_rms_w 278.9 278.9 =
mean_abs_grid_w 117.0 117.0 =
share_imbalance_w 0.0 0.0 =
avoidable_import_wh 81.4 81.4 =
avoidable_export_wh 35.5 35.5 =
cost_regret_ct 1.36 1.36 =
battery_travel_w_per_h 33179.4 33179.4 =
single_venus_washer — settle 0.0→0.0s, overshoot 0.0→0.0W, RMS 61.0→61.0W
Metric Base Head Δ
settle_mean_s 0.0 0.0 =
settle_p95_s 0.0 0.0 =
unsettled_events 0.0 0.0 =
overshoot_mean_w 0.0 0.0 =
overshoot_max_w 0.0 0.0 =
band_crossings_per_h 320.4 320.4 =
grid_p2p_w 196.1 196.1 =
grid_rms_w 61.1 61.1 =
steady_rms_w 61.0 61.0 =
mean_abs_grid_w 40.6 40.6 =
share_imbalance_w 0.0 0.0 =
avoidable_import_wh 11.3 11.3 =
avoidable_export_wh 9.0 9.0 =
cost_regret_ct 0.27 0.27 =
battery_travel_w_per_h 24290.4 24290.4 =
two_venus/eff — settle 18.1→18.1s, overshoot 126.1→126.1W, RMS 14.0→14.0W
Metric Base Head Δ
settle_mean_s 18.1 18.1 =
settle_p95_s 23.0 23.0 =
unsettled_events 0.0 0.0 =
overshoot_mean_w 70.7 70.7 =
overshoot_max_w 126.1 126.1 =
band_crossings_per_h 33.6 33.6 =
grid_p2p_w 26.2 26.2 =
grid_rms_w 221.6 221.6 =
steady_rms_w 14.0 14.0 =
mean_abs_grid_w 43.1 43.1 =
share_imbalance_w 166.4 166.4 =
avoidable_import_wh 25.7 25.7 =
avoidable_export_wh 17.3 17.3 =
cost_regret_ct 0.64 0.64 =
battery_travel_w_per_h 22029.2 22029.2 =
two_venus/fair — settle 18.4→18.4s, overshoot 116.7→116.7W, RMS 13.8→13.8W
Metric Base Head Δ
settle_mean_s 18.4 18.4 =
settle_p95_s 24.4 24.4 =
unsettled_events 0.0 0.0 =
overshoot_mean_w 94.4 94.4 =
overshoot_max_w 116.7 116.7 =
band_crossings_per_h 21.6 21.6 =
grid_p2p_w 23.1 23.1 =
grid_rms_w 217.6 217.6 =
steady_rms_w 13.8 13.8 =
mean_abs_grid_w 41.4 41.4 =
share_imbalance_w 18.8 18.8 =
avoidable_import_wh 24.2 24.2 =
avoidable_export_wh 17.1 17.1 =
cost_regret_ct 0.59 0.59 =
battery_travel_w_per_h 19385.4 19385.4 =
two_venus_noisy/eff — settle 0.0→0.0s, overshoot 0.0→0.0W, RMS 94.3→94.3W
Metric Base Head Δ
settle_mean_s 0.0 0.0 =
settle_p95_s 0.0 0.0 =
unsettled_events 0.0 0.0 =
overshoot_mean_w 0.0 0.0 =
overshoot_max_w 0.0 0.0 =
band_crossings_per_h 2898.0 2898.0 =
grid_p2p_w 294.5 294.5 =
grid_rms_w 94.3 94.3 =
steady_rms_w 94.3 94.3 =
mean_abs_grid_w 79.4 79.4 =
share_imbalance_w 26.9 26.9 =
avoidable_import_wh 43.6 43.6 =
avoidable_export_wh 35.8 35.8 =
cost_regret_ct 1.02 1.02 =
battery_travel_w_per_h 23402.6 23402.6 =
two_venus_noisy/fair — settle 0.0→0.0s, overshoot 0.0→0.0W, RMS 94.2→94.2W
Metric Base Head Δ
settle_mean_s 0.0 0.0 =
settle_p95_s 0.0 0.0 =
unsettled_events 0.0 0.0 =
overshoot_mean_w 0.0 0.0 =
overshoot_max_w 0.0 0.0 =
band_crossings_per_h 2893.6 2893.6 =
grid_p2p_w 294.1 294.1 =
grid_rms_w 94.2 94.2 =
steady_rms_w 94.2 94.2 =
mean_abs_grid_w 79.4 79.4 =
share_imbalance_w 26.4 26.4 =
avoidable_import_wh 43.6 43.6 =
avoidable_export_wh 35.8 35.8 =
cost_regret_ct 1.02 1.02 =
battery_travel_w_per_h 22778.8 22778.8 =
two_venus_slow/fair — settle 41.8→41.8s, overshoot 174.5→174.5W, RMS 14.0→14.0W
Metric Base Head Δ
settle_mean_s 41.8 41.8 =
settle_p95_s 52.8 52.8 =
unsettled_events 0.0 0.0 =
overshoot_mean_w 56.6 56.6 =
overshoot_max_w 174.5 174.5 =
band_crossings_per_h 10.4 10.4 =
grid_p2p_w 81.8 81.8 =
grid_rms_w 303.7 303.7 =
steady_rms_w 14.0 14.0 =
mean_abs_grid_w 76.9 76.9 =
share_imbalance_w 24.4 24.4 =
avoidable_import_wh 41.5 41.5 =
avoidable_export_wh 35.3 35.3 =
cost_regret_ct 0.96 0.96 =
battery_travel_w_per_h 18563.6 18563.6 =
two_venus_solar/eff — settle 26.0→26.0s, overshoot 396.6→396.6W, RMS 20.4→20.4W
Metric Base Head Δ
settle_mean_s 26.0 26.0 =
settle_p95_s 44.3 44.3 =
unsettled_events 1.6 1.6 =
overshoot_mean_w 100.5 100.5 =
overshoot_max_w 396.6 396.6 =
band_crossings_per_h 40.4 40.4 =
grid_p2p_w 60.2 60.2 =
grid_rms_w 228.7 228.7 =
steady_rms_w 20.4 20.4 =
mean_abs_grid_w 51.9 51.9 =
share_imbalance_w 69.3 69.3 =
avoidable_import_wh 42.4 42.4 =
avoidable_export_wh 35.4 35.4 =
cost_regret_ct 0.99 0.99 =
battery_travel_w_per_h 26336.0 26336.0 =
two_venus_solar/fair — settle 25.9→25.9s, overshoot 151.4→151.4W, RMS 20.4→20.4W
Metric Base Head Δ
settle_mean_s 25.9 25.9 =
settle_p95_s 52.1 52.1 =
unsettled_events 1.4 1.4 =
overshoot_mean_w 98.1 98.1 =
overshoot_max_w 151.4 151.4 =
band_crossings_per_h 30.7 30.7 =
grid_p2p_w 59.8 59.8 =
grid_rms_w 225.6 225.6 =
steady_rms_w 20.4 20.4 =
mean_abs_grid_w 51.1 51.1 =
share_imbalance_w 31.3 31.3 =
avoidable_import_wh 40.1 40.1 =
avoidable_export_wh 36.5 36.5 =
cost_regret_ct 0.91 0.91 =
battery_travel_w_per_h 24206.8 24206.8 =
two_venus_trace/eff — settle 0.0→0.0s, overshoot 0.0→0.0W, RMS 283.1→283.1W
Metric Base Head Δ
settle_mean_s 0.0 0.0 =
settle_p95_s 0.0 0.0 =
unsettled_events 0.0 0.0 =
overshoot_mean_w 0.0 0.0 =
overshoot_max_w 0.0 0.0 =
band_crossings_per_h 307.6 307.6 =
grid_p2p_w 744.9 744.9 =
grid_rms_w 282.1 282.1 =
steady_rms_w 283.1 283.1 =
mean_abs_grid_w 122.0 122.0 =
share_imbalance_w 398.3 398.3 =
avoidable_import_wh 80.0 80.0 =
avoidable_export_wh 42.0 42.0 =
cost_regret_ct 2.06 2.06 =
battery_travel_w_per_h 47999.0 47999.0 =
two_venus_trace/fair — settle 0.0→0.0s, overshoot 0.0→0.0W, RMS 282.1→282.1W
Metric Base Head Δ
settle_mean_s 0.0 0.0 =
settle_p95_s 0.0 0.0 =
unsettled_events 0.0 0.0 =
overshoot_mean_w 0.0 0.0 =
overshoot_max_w 0.0 0.0 =
band_crossings_per_h 310.0 310.0 =
grid_p2p_w 732.2 732.2 =
grid_rms_w 281.1 281.1 =
steady_rms_w 282.1 282.1 =
mean_abs_grid_w 121.1 121.1 =
share_imbalance_w 30.3 30.3 =
avoidable_import_wh 79.0 79.0 =
avoidable_export_wh 42.0 42.0 =
cost_regret_ct 2.04 2.04 =
battery_travel_w_per_h 46054.4 46054.4 =
venus_d_plus_c/eff — settle 20.1→20.1s, overshoot 128.9→128.9W, RMS 14.7→14.7W
Metric Base Head Δ
settle_mean_s 20.1 20.1 =
settle_p95_s 31.9 31.9 =
unsettled_events 0.0 0.0 =
overshoot_mean_w 78.9 78.9 =
overshoot_max_w 128.9 128.9 =
band_crossings_per_h 35.2 35.2 =
grid_p2p_w 28.0 28.0 =
grid_rms_w 214.7 214.7 =
steady_rms_w 14.7 14.7 =
mean_abs_grid_w 41.6 41.6 =
share_imbalance_w 167.3 167.3 =
avoidable_import_wh 24.9 24.9 =
avoidable_export_wh 16.7 16.7 =
cost_regret_ct 0.61 0.61 =
battery_travel_w_per_h 23208.0 23208.0 =
venus_d_plus_c/fair — settle 21.6→21.6s, overshoot 121.0→121.0W, RMS 14.6→14.6W
Metric Base Head Δ
settle_mean_s 21.6 21.6 =
settle_p95_s 32.5 32.5 =
unsettled_events 0.0 0.0 =
overshoot_mean_w 90.6 90.6 =
overshoot_max_w 121.0 121.0 =
band_crossings_per_h 24.8 24.8 =
grid_p2p_w 27.4 27.4 =
grid_rms_w 211.5 211.5 =
steady_rms_w 14.6 14.6 =
mean_abs_grid_w 40.8 40.8 =
share_imbalance_w 30.2 30.2 =
avoidable_import_wh 24.1 24.1 =
avoidable_export_wh 16.7 16.7 =
cost_regret_ct 0.59 0.59 =
battery_travel_w_per_h 21212.8 21212.8 =

📊 Open the interactive reportsteering-eval-report.html, a single self-contained file (opens in-browser; download it if your browser blocks inline scripts).

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@web/ts/generate.ts`:
- Around line 297-304: The `generateEsphome()` flow is emitting a duplicate
top-level `http_request:` block from the meter polling branch, which can
overwrite the shared HTTP settings. Update the logic around the `RX_BUFFER` push
so it contributes `useragent`, `timeout`, and `buffer_size_rx` to the existing
shared `http_request` config instead of appending a second block; use the
existing `http_request` handling in `generateEsphome()` for
`marstek_registration` and `cloud_reporting` as the single source of truth.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 89993f0f-b88a-4618-a42f-76074121547f

📥 Commits

Reviewing files that changed from the base of the PR and between f632a3d and d4ef1b4.

📒 Files selected for processing (5)
  • AGENTS.md
  • CHANGELOG.md
  • docs/esphome-powermeters.md
  • web/ts/generate.test.ts
  • web/ts/generate.ts

Comment thread web/ts/generate.ts
ESPHome allows only one top-level http_request:. An HTTP-polled meter
emits one (useragent + RX buffer) and marstek_registration/cloud_reporting
emit another (20s timeout); with both enabled the generated YAML had two
http_request: blocks, so ESPHome would drop either the timeout or the new
RX buffer. Merge into the meter's single block, bumping its timeout to 20s
when a slow feature also needs it. Add a regression test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FEzZ7zoMfEEZt2cyrdiAV4
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant