Skip to content

feat: Add shaper_live_pwr method#516

Merged
firstof9 merged 3 commits intomainfrom
add-shaper-live-pwr
Feb 20, 2026
Merged

feat: Add shaper_live_pwr method#516
firstof9 merged 3 commits intomainfrom
add-shaper-live-pwr

Conversation

@firstof9
Copy link
Owner

@firstof9 firstof9 commented Feb 20, 2026

fixes #515
related to firstof9/openevse#540

Summary by CodeRabbit

  • New Features

    • Added ability to set live shaper power remotely; respects device firmware compatibility and logs outcomes.
  • Tests

    • Added tests covering setting live shaper power (including zero) and verifying behavior on unsupported firmware.
  • Chores

    • Removed unused test imports.

@coderabbitai
Copy link

coderabbitai bot commented Feb 20, 2026

No actionable comments were generated in the recent review. 🎉


📝 Walkthrough

Walkthrough

Adds async OpenEVSE.set_shaper_live_pwr(power: int) to POST {"shaper_live_pwr": power} to the device /status endpoint with firmware gating, logging of unsupported firmware and responses; includes unit tests and a minor test import cleanup.

Changes

Cohort / File(s) Summary
OpenEVSE core
openevsehttp/__main__.py
Added async set_shaper_live_pwr(power: int) that enforces firmware >= 4.0.0, logs a not-supported message for older firmware, constructs {"shaper_live_pwr": power}, POSTs to /status, and logs the response.
Tests — new behavior
tests/test_main.py
Added test_set_shaper_live_power to exercise setting shaper_live_pwr (e.g., 210 and 0), assert POST/response logging for supported firmware, and assert UnsupportedFeature + log for older firmware using test fixtures and a mocked HTTP client.
Tests — import cleanup
tests/test_external_session.py
Removed unused patch import from unittest.mock (now only AsyncMock, MagicMock are imported).

Sequence Diagram(s)

sequenceDiagram
    participant Caller
    participant OpenEVSE
    participant ChargerAPI

    Caller->>OpenEVSE: call set_shaper_live_pwr(power)
    OpenEVSE->>OpenEVSE: check firmware version
    alt firmware >= 4.0.0
        OpenEVSE->>ChargerAPI: POST /status { "shaper_live_pwr": power }
        ChargerAPI-->>OpenEVSE: HTTP response
        OpenEVSE-->>Caller: return / log response
    else older firmware
        OpenEVSE-->>Caller: raise UnsupportedFeature / log not supported
    end
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 I hop and tap the bytes with cheer,
A tiny POST makes power appear,
"shaper_live_pwr" sent in a blink,
Logs nod back before I blink,
A rabbit's code — concise and clear.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding a new shaper_live_pwr method to the OpenEVSE class.
Linked Issues check ✅ Passed The implementation meets issue #515's requirement by adding a method that sends HTTP POST to /status with JSON payload {'shaper_live_pwr': int}.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing the shaper_live_pwr feature. Cleanup of unused imports is a minor scope-appropriate improvement.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch add-shaper-live-pwr

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 Pylint (4.0.4)
tests/test_main.py

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 and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (4)
openevsehttp/__main__.py (2)

1316-1316: Method name and parameter name are identical — rename the parameter.

shaper_live_pwr(self, shaper_live_pwr: int) uses the same identifier for both the method and its parameter. While Python resolves it correctly at runtime (the parameter shadows the method name inside the body), it harms readability and can cause confusion when reading or calling the method.

♻️ Suggested rename
-    async def shaper_live_pwr(self, shaper_live_pwr: int) -> None:
-        """Send pushed sensor data to shaper."""
-        url = f"{self.url}status"
-        data = {"shaper_live_pwr": shaper_live_pwr}
+    async def shaper_live_pwr(self, value: int) -> None:
+        """Send pushed sensor data to shaper."""
+        url = f"{self.url}status"
+        data = {"shaper_live_pwr": value}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openevsehttp/__main__.py` at line 1316, The method shaper_live_pwr currently
uses the same identifier for the method and its parameter, which is confusing;
rename the parameter (for example to value, power, or new_shaper_live_pwr) in
the async def shaper_live_pwr(...) signature, update the type hint accordingly,
and adjust all references inside the method body to the new parameter name; also
update any callers, docstrings, and tests that pass that parameter to use the
new name to ensure consistency.

1315-1323: Add version guard or document intentional omission.

shaper_live_pwr lacks the _version_check() guard present in sibling POST methods (grid_voltage, self_production, soc). Test fixtures show shaper is unavailable in firmware 2.9.1 but available in 4.1.2. Either add a guard (likely _version_check("4.0.0") or _version_check("4.1.0") based on patterns) or include a comment explaining why the feature is universally supported.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openevsehttp/__main__.py` around lines 1315 - 1323, The shaper_live_pwr
method is missing the firmware version guard used by sibling POST methods
(grid_voltage, self_production, soc); add a call to _version_check (e.g.,
_version_check("4.1.0") or whichever minimum version matches other
shaper-related endpoints) at the start of shaper_live_pwr to early-return or
raise when unsupported, or add a clear comment above shaper_live_pwr explaining
that this endpoint is intentionally available for all firmware versions;
reference the shaper_live_pwr method and the existing _version_check utility
when making the change.
tests/test_main.py (2)

1274-1286: Test only covers the happy path — consider adding an edge-case scenario.

Comparable tests (test_soc, test_self_production) validate at least one additional scenario (empty data, UnsupportedFeature, invalid input). This test only verifies a single successful POST. At minimum, testing a zero or negative value would ensure the method (or a future validation guard) behaves as expected at the boundaries.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/test_main.py` around lines 1274 - 1286, Add an edge-case test for
shaper_live_pwr in addition to the happy path: update or create a new test
(e.g., alongside test_set_shaper_live_power) that calls
test_charger.shaper_live_pwr with a boundary value such as 0 (and optionally a
negative value) and asserts the expected behavior — for example that it posts
the correct payload, handles an empty response/body, or raises/handles
UnsupportedFeature or a validation error depending on implementation; use the
same mock_aioclient.post to simulate the service returning either an empty body,
an error status, or a payload reflecting the boundary value and assert the
corresponding log messages or exceptions to mirror the existing checks in
test_set_shaper_live_power.

1281-1281: repeat=True is unnecessary — the method is called exactly once in this test.

♻️ Proposed fix
     mock_aioclient.post(
         TEST_URL_STATUS,
         status=200,
         body='{"shaper_live_pwr": 210}',
-        repeat=True,
     )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/test_main.py` at line 1281, Remove the unnecessary repeat=True argument
from the call in tests/test_main.py (the call that currently includes
"repeat=True"); locate the invocation that passes repeat=True and delete that
keyword argument so the method is called with its default single-invocation
behavior (no other code changes required unless tests assert repeated behavior,
in which case adjust those assertions accordingly).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@openevsehttp/__main__.py`:
- Line 1316: The method shaper_live_pwr currently uses the same identifier for
the method and its parameter, which is confusing; rename the parameter (for
example to value, power, or new_shaper_live_pwr) in the async def
shaper_live_pwr(...) signature, update the type hint accordingly, and adjust all
references inside the method body to the new parameter name; also update any
callers, docstrings, and tests that pass that parameter to use the new name to
ensure consistency.
- Around line 1315-1323: The shaper_live_pwr method is missing the firmware
version guard used by sibling POST methods (grid_voltage, self_production, soc);
add a call to _version_check (e.g., _version_check("4.1.0") or whichever minimum
version matches other shaper-related endpoints) at the start of shaper_live_pwr
to early-return or raise when unsupported, or add a clear comment above
shaper_live_pwr explaining that this endpoint is intentionally available for all
firmware versions; reference the shaper_live_pwr method and the existing
_version_check utility when making the change.

In `@tests/test_main.py`:
- Around line 1274-1286: Add an edge-case test for shaper_live_pwr in addition
to the happy path: update or create a new test (e.g., alongside
test_set_shaper_live_power) that calls test_charger.shaper_live_pwr with a
boundary value such as 0 (and optionally a negative value) and asserts the
expected behavior — for example that it posts the correct payload, handles an
empty response/body, or raises/handles UnsupportedFeature or a validation error
depending on implementation; use the same mock_aioclient.post to simulate the
service returning either an empty body, an error status, or a payload reflecting
the boundary value and assert the corresponding log messages or exceptions to
mirror the existing checks in test_set_shaper_live_power.
- Line 1281: Remove the unnecessary repeat=True argument from the call in
tests/test_main.py (the call that currently includes "repeat=True"); locate the
invocation that passes repeat=True and delete that keyword argument so the
method is called with its default single-invocation behavior (no other code
changes required unless tests assert repeated behavior, in which case adjust
those assertions accordingly).

@firstof9 firstof9 added the enhancement New feature or request label Feb 20, 2026
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
tests/test_main.py (1)

1293-1295: Missing response log assertion for the zero-power case.

The first scenario (power=210, lines 1283-1286) asserts both the posting and the response log, but the zero-power path only checks the posting log. For consistency and completeness, assert the response as well.

♻️ Proposed addition
     with caplog.at_level(logging.DEBUG):
         await test_charger.set_shaper_live_pwr(0)
         assert "Posting shaper data: {'shaper_live_pwr': 0}" in caplog.text
+        assert "Shaper response: {'shaper_live_pwr': 0}" in caplog.text
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/test_main.py` around lines 1293 - 1295, The zero-power test block is
missing the assertion that the response log contains the expected response
message; after calling test_charger.set_shaper_live_pwr(0) and asserting the
posting log, add an assertion that caplog.text includes the response log string
used elsewhere (the same response-check pattern as the 210W case) to verify the
response was logged; locate the zero-power block around the call to
test_charger.set_shaper_live_pwr and mirror the response assertion used with the
210 case to keep tests consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/test_main.py`:
- Around line 1297-1302: The pytest.raises block currently wraps
test_charger_v2.update(), set_shaper_live_pwr(210), the caplog assertion, and
ws_disconnect(), but set_shaper_live_pwr raises UnsupportedFeature immediately
so the assertion and ws_disconnect() are never reached; fix by calling await
test_charger_v2.update() outside the pytest.raises context, then use with
pytest.raises(UnsupportedFeature): await
test_charger_v2.set_shaper_live_pwr(210), and after that assert "Feature not
supported for older firmware." in caplog.text and finally call await
test_charger_v2.ws_disconnect() to ensure cleanup; keep references to
UnsupportedFeature, set_shaper_live_pwr, update, ws_disconnect, and caplog to
locate the code.

---

Nitpick comments:
In `@tests/test_main.py`:
- Around line 1293-1295: The zero-power test block is missing the assertion that
the response log contains the expected response message; after calling
test_charger.set_shaper_live_pwr(0) and asserting the posting log, add an
assertion that caplog.text includes the response log string used elsewhere (the
same response-check pattern as the 210W case) to verify the response was logged;
locate the zero-power block around the call to test_charger.set_shaper_live_pwr
and mirror the response assertion used with the 210 case to keep tests
consistent.

@firstof9
Copy link
Owner Author

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Feb 20, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@firstof9 firstof9 merged commit 58ee0c4 into main Feb 20, 2026
3 checks passed
@firstof9 firstof9 deleted the add-shaper-live-pwr branch February 20, 2026 20:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature Request]: shaper_live_pwr HTTP POST function

1 participant