Skip to content

Gate demand response commands on dr_setting_use capability#117

Merged
eman merged 3 commits into
mainfrom
fix/114-dr-capability-gate
Jul 23, 2026
Merged

Gate demand response commands on dr_setting_use capability#117
eman merged 3 commits into
mainfrom
fix/114-dr-capability-gate

Conversation

@eman

@eman eman commented Jul 23, 2026

Copy link
Copy Markdown
Owner

Summary

  • enable_demand_response / disable_demand_response (src/nwp500/mqtt/control.py) were dispatched unconditionally, even though the dr_setting_use capability flag exists on DeviceFeature (models/feature.py).
  • Every other controllable feature follows the pattern: flag in feature.py + entry in _CAPABILITY_MAP + @requires_capability(...) decorator (set_powerpower_use, set_dhw_modedhw_use, configure_tou_scheduleprogram_reservation_use, etc). DR was the one gap.
  • Added "dr_setting_use": lambda f: bool(f.dr_setting_use) to _CAPABILITY_MAP and decorated both methods with @requires_capability("dr_setting_use").

Fixes #114

Test plan

  • tests/test_device_capabilities.py: new test_dr_setting_use_capability, updated test_get_available_controls for the new map entry (8 → 9 capabilities).
  • tests/test_protocol_correctness.py: new TestDemandResponseCapabilityGate verifying both commands are blocked when dr_setting_use is falsy and allowed when truthy.
  • Full suite: 608 passed, 4 skipped.

enable_demand_response/disable_demand_response were dispatched
unconditionally even though the dr_setting_use capability flag exists
on DeviceFeature. Every other controllable feature follows
flag + _CAPABILITY_MAP entry + @requires_capability, so DR was the one
gap. Add "dr_setting_use" to _CAPABILITY_MAP and decorate both methods.

Fixes #114

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR closes the capability-gating gap for Demand Response (DR) controls by wiring the existing DeviceFeature.dr_setting_use flag into the capability checker and enforcing it via @requires_capability(...) on the MQTT control methods. This aligns DR with the established “feature flag + _CAPABILITY_MAP entry + decorator gate” pattern used by other controls.

Changes:

  • Added dr_setting_use to MqttDeviceCapabilityChecker._CAPABILITY_MAP.
  • Gated enable_demand_response / disable_demand_response behind @requires_capability("dr_setting_use").
  • Added/updated tests to validate capability registration and gating behavior (Fixes #114).

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
src/nwp500/device_capabilities.py Registers dr_setting_use as a controllable capability so it can be checked centrally.
src/nwp500/mqtt/control.py Applies @requires_capability("dr_setting_use") to DR enable/disable commands to prevent unsupported dispatch.
tests/test_device_capabilities.py Extends capability-map tests to include dr_setting_use and updates expected control count.
tests/test_protocol_correctness.py Adds protocol-level regression tests asserting DR commands are blocked when unsupported (and intended to be allowed when supported).

Comment on lines +331 to +340
@pytest.mark.asyncio
async def test_enable_allowed_when_supported(self, mock_device):
controller, publish = _make_controller()
controller._get_device_features = AsyncMock(
return_value=MagicMock(dr_setting_use=True)
)

await controller.enable_demand_response(mock_device)
publish.assert_awaited_once()

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Fixed in ca1cf6e — added test_disable_allowed_when_supported so both commands' allowed-path are covered, not just enable.

eman added 2 commits July 23, 2026 08:22
Review feedback on #117 (Copilot): the PR description claimed both
enable_demand_response and disable_demand_response were verified
allowed-when-supported, but only enable_demand_response had that
assertion. Add the matching test for disable_demand_response so a
regression that gates one command but not the other would be caught.
Resolves conflicts with #115 (docstring fix) and #116 (freeze
protection validation), both merged to main after this branch was cut.
Conflicts were purely additive: dr_setting_use and
freeze_protection_use both added to _CAPABILITY_MAP, and their
respective test classes both added to test_protocol_correctness.py /
test_device_capabilities.py. Combined capability count is now 10.
@eman
eman merged commit d236b11 into main Jul 23, 2026
7 checks passed
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.

dr_setting_use capability exists but demand-response commands are not capability-gated

2 participants