Skip to content

Conversation

@kbx81
Copy link
Member

@kbx81 kbx81 commented Oct 2, 2025

What does this implement/fix?

Implements a feature flags system for climate entities to replace multiple individual boolean capability flags. This addresses home-assistant/core#153331 by introducing a new REQUIRES_TWO_POINT_TARGET_TEMPERATURE flag to distinguish between devices that optionally support dual setpoint vs. those that require it.

Changes

  • Adds feature_flags field (uint32) to ListEntitiesClimateResponse in api.proto
  • Introduces ClimateFeature IntFlag enum with flags for all climate capabilities
  • Deprecates 5 boolean fields (but keeps them for backward compatibility):
    • supports_current_temperature
    • supports_two_point_target_temperature
    • supports_action
    • supports_current_humidity
    • supports_target_humidity
  • Adds new REQUIRES_TWO_POINT_TARGET_TEMPERATURE flag to handle mandatory dual setpoint
  • Bumps API version from 1.12 to 1.13

Breaking Changes

IMPORTANT: This PR is marked as breaking to alert API consumers that migration is required, even though nothing breaks immediately.

The boolean fields (supports_current_temperature, supports_two_point_target_temperature, supports_action, supports_current_humidity, supports_target_humidity) are deprecated and will be removed in a future release (likely with another major version bump).

Why this is marked breaking:

  1. To fix the bug (No longer able to set both setpoints of ESPHome bang-bang cooler controller home-assistant/core#153331), consumers need access to the new REQUIRES_TWO_POINT_TARGET_TEMPERATURE flag, which is only available via the feature flags system
  2. To enable future migration: This gives API consumers advance notice to migrate their code now, before the deprecated fields are actually removed
  3. Future compatibility: When the deprecated fields are removed in a future release, code that has already migrated will not be affected

What will break later when fields are removed:

  • Any code still directly accessing the deprecated boolean fields

All code must migrate to using the feature flags system now to access the new functionality and avoid breakage in the future.

Migration required:

# Old code (incomplete with API 1.13+, missing new flags):
if climate_info.supports_current_temperature:
    process_current_temp()

# New code (works with all API versions and includes all flags):
flags = climate_info.supported_feature_flags_compat(api_version)
if flags & ClimateFeature.SUPPORTS_CURRENT_TEMPERATURE:
    process_current_temp()

# Access new functionality only available via feature flags:
if flags & ClimateFeature.REQUIRES_TWO_POINT_TARGET_TEMPERATURE:
    handle_required_dual_setpoint()

The supported_feature_flags_compat(api_version) method handles both old and new API versions:

  • For API < 1.13: Maps the old boolean fields to feature flags
  • For API >= 1.13: Returns the feature_flags field directly (includes all flags, old and new)

See also:

Types of changes

  • Bugfix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Code quality improvements to existing code or addition of tests
  • Other

Related issue or feature (if applicable):

  • fixes

Pull request in esphome (if applicable):

  • esphome/esphome#

Checklist:

  • The code change is tested and works locally.
  • If api.proto was modified, a linked pull request has been made to esphome with the same changes.
  • Tests have been added to verify that the new code works (under tests/ folder).

@codecov
Copy link

codecov bot commented Oct 2, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (cfdb7a4) to head (b31a13e).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##              main     #1376   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           22        22           
  Lines         3287      3310   +23     
=========================================
+ Hits          3287      3310   +23     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@codspeed-hq
Copy link

codspeed-hq bot commented Oct 2, 2025

CodSpeed Performance Report

Merging #1376 will not alter performance

Comparing kbx81:20251001-add-dual-setpoint-required-flag (b31a13e) with main (cfdb7a4)1

Summary

✅ 11 untouched

Footnotes

  1. No successful run was found on main (ea093a6) during the generation of this report, so cfdb7a4 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

@kbx81 kbx81 marked this pull request as ready for review October 2, 2025 21:57
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 2, 2025

Walkthrough

Added a uint32 feature_flags to ListEntitiesClimateResponse in the protobuf, introduced a ClimateFeature IntFlag and feature_flags: int = 0 on ClimateInfo with a compatibility helper, and bumped the HelloRequest API minor version from 12 to 13. No control-flow or error-handling changes.

Changes

Cohort / File(s) Summary
Protocol schema update
aioesphomeapi/api.proto
Added uint32 feature_flags = 27; to message ListEntitiesClimateResponse (with deprecation comments on related fields).
Python model update
aioesphomeapi/model.py
Added ClimateFeature (enum.IntFlag); added feature_flags: int = 0 to ClimateInfo; added ClimateInfo.supported_feature_flags_compat(api_version) to map legacy boolean capability fields to flags for older API versions.
Handshake/version bump
aioesphomeapi/connection.py
Bumped HelloRequest API minor version from 12 to 13 in _make_hello_request.
Tests
tests/test_model.py
Added test_climate_info_supported_feature_flags_compat validating flag mapping across API versions and combinations; updated imports to include ClimateFeature.

Sequence Diagram(s)

(omitted — changes do not introduce new control-flow requiring a sequence diagram)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

minor

Suggested reviewers

  • bdraco

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title Check ✅ Passed The title succinctly and accurately conveys the main change of adding a feature_flags field to replace multiple boolean flags in the climate component, reflecting the core update in the pull request without extraneous detail.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
Description Check ✅ Passed The pull request description clearly outlines the addition of the feature_flags field, the introduction of the ClimateFeature enum, deprecation of existing boolean fields, and the API version bump, which directly corresponds to the summarized code changes. It specifies the intent to address a known issue, details migration guidance, and references related upstream pull requests. The description is specific, on-topic, and describes relevant parts of the changeset. Therefore, it meets the criteria for a valid pull request description.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

@kbx81 kbx81 changed the title Add requires_two_point_target_temperature flag Implement feature_flags for climate Oct 4, 2025
Copy link
Contributor

@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: 0

🧹 Nitpick comments (1)
aioesphomeapi/api.proto (1)

974-999: Mark the deprecated climate booleans with protobuf deprecation markers

You flagged these booleans as deprecated in comments, but unlike the rest of the schema we aren’t setting [deprecated=true]. Adding the annotation keeps codegen warnings consistent and nudges consumers to adopt feature_flags.

-  bool supports_current_temperature = 5; // Deprecated: use feature_flags
-  bool supports_two_point_target_temperature = 6; // Deprecated: use feature_flags
+  bool supports_current_temperature = 5 [deprecated=true]; // Use feature_flags
+  bool supports_two_point_target_temperature = 6 [deprecated=true]; // Use feature_flags
@@
-  bool supports_action = 12; // Deprecated: use feature_flags
+  bool supports_action = 12 [deprecated=true]; // Use feature_flags
@@
-  bool supports_current_humidity = 22; // Deprecated: use feature_flags
-  bool supports_target_humidity = 23; // Deprecated: use feature_flags
+  bool supports_current_humidity = 22 [deprecated=true]; // Use feature_flags
+  bool supports_target_humidity = 23 [deprecated=true]; // Use feature_flags
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 615158b and 73d44cc.

📒 Files selected for processing (2)
  • aioesphomeapi/api.proto (3 hunks)
  • aioesphomeapi/model.py (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • aioesphomeapi/model.py
🧰 Additional context used
📓 Path-based instructions (1)
**

⚙️ CodeRabbit configuration file

  • Do not generate or add any sequence diagrams

Files:

  • aioesphomeapi/api.proto
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Run benchmarks

Copy link
Contributor

@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: 0

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

339-376: Well-structured compatibility test.

The test correctly validates the backward compatibility logic for ClimateInfo feature flags across API versions. The parametrization covers individual flags for API < 1.13 and demonstrates the new feature_flags field for API >= 1.13.

Consider adding optional test cases to improve coverage:

  • Combinations of multiple boolean flags for API < 1.13 (e.g., supports_current_temperature=True, supports_action=True)
  • Distinct testing of SUPPORTS_TWO_POINT_TARGET_TEMPERATURE vs REQUIRES_TWO_POINT_TARGET_TEMPERATURE flags for API >= 1.13
  • Edge case verification at exactly API version (1, 13)

Example test case for multiple flags:

(
    ClimateInfo(
        supports_current_temperature=True,
        supports_action=True,
    ),
    (1, 12),
    ClimateFeature.SUPPORTS_CURRENT_TEMPERATURE | ClimateFeature.SUPPORTS_ACTION,
),
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between faec940 and 50880a5.

📒 Files selected for processing (1)
  • tests/test_model.py (2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**

⚙️ CodeRabbit configuration file

  • Do not generate or add any sequence diagrams

Files:

  • tests/test_model.py
🧬 Code graph analysis (1)
tests/test_model.py (1)
aioesphomeapi/model.py (4)
  • ClimateFeature (115-121)
  • ClimateInfo (654-719)
  • supported_feature_flags_compat (695-710)
  • APIVersion (100-102)
🔇 Additional comments (1)
tests/test_model.py (1)

86-86: LGTM!

The import of ClimateFeature is correctly added to support the new compatibility test.

@kbx81 kbx81 changed the title Implement feature_flags for climate [climate] Implement feature flags field to replace multiple bools Oct 7, 2025
Copy link
Contributor

@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: 0

🧹 Nitpick comments (1)
aioesphomeapi/model.py (1)

115-122: LGTM! ClimateFeature enum follows established pattern.

The ClimateFeature IntFlag enum is well-defined and follows the same pattern as BluetoothProxyFeature and VoiceAssistantFeature in the codebase. The bit-shift values are correct and non-overlapping.

Consider adding docstring comments to clarify the semantic relationship between SUPPORTS_TWO_POINT_TARGET_TEMPERATURE and REQUIRES_TWO_POINT_TARGET_TEMPERATURE flags (e.g., whether requiring implies supporting).

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 50880a5 and 696c767.

📒 Files selected for processing (2)
  • aioesphomeapi/api.proto (3 hunks)
  • aioesphomeapi/model.py (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • aioesphomeapi/api.proto
🧰 Additional context used
📓 Path-based instructions (1)
**

⚙️ CodeRabbit configuration file

  • Do not generate or add any sequence diagrams

Files:

  • aioesphomeapi/model.py
🧬 Code graph analysis (1)
aioesphomeapi/model.py (1)
aioesphomeapi/client_base.py (1)
  • api_version (329-332)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: py 3.12 on windows-latest (skip_cython)
  • GitHub Check: Run benchmarks
🔇 Additional comments (2)
aioesphomeapi/model.py (2)

655-655: LGTM! Field addition follows dataclass conventions.

The feature_flags: int = 0 field is correctly added with an appropriate default value for a flags field.


695-710: Verify flag mapping for two-point target temperature compatibility.

The compatibility method correctly follows the established pattern (similar to bluetooth_proxy_feature_flags_compat and voice_assistant_feature_flags_compat). The API version check at 1.13 aligns with the version bump in connection.py.

However, the mapping on line 702 sets only REQUIRES_TWO_POINT_TARGET_TEMPERATURE without also setting SUPPORTS_TWO_POINT_TARGET_TEMPERATURE. While the comment indicates this is intentional to "mimic previous behavior," verify that:

  1. The test coverage in tests/test_model.py validates this specific flag combination for old API versions
  2. Consumer code correctly handles cases where REQUIRES is set without SUPPORTS for backward compatibility
  3. For new devices (API >= 1.13), devices that require two-point target temperature set both flags in feature_flags

Based on past review comments, this implementation aligns with the reviewer's suggestions.

Copy link
Contributor

@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: 0

🧹 Nitpick comments (2)
aioesphomeapi/api.proto (2)

990-992: Make deprecations explicit and consistent ([deprecated=true] + version note).

Elsewhere in this proto, deprecated fields use [deprecated=true] and “Deprecated in API version …”. Do the same here to guide consumers and keep consistency.

-  bool supports_current_temperature = 5; // Deprecated: use feature_flags
+  // Deprecated in API version 1.13: use feature_flags
+  bool supports_current_temperature = 5 [deprecated=true];

-  bool supports_two_point_target_temperature = 6; // Deprecated: use feature_flags
+  // Deprecated in API version 1.13: use feature_flags
+  bool supports_two_point_target_temperature = 6 [deprecated=true];

-  bool supports_action = 12; // Deprecated: use feature_flags
+  // Deprecated in API version 1.13: use feature_flags
+  bool supports_action = 12 [deprecated=true];

-  bool supports_current_humidity = 22; // Deprecated: use feature_flags
+  // Deprecated in API version 1.13: use feature_flags
+  bool supports_current_humidity = 22 [deprecated=true];

-  bool supports_target_humidity = 23; // Deprecated: use feature_flags
+  // Deprecated in API version 1.13: use feature_flags
+  bool supports_target_humidity = 23 [deprecated=true];

Also applies to: 1000-1001, 1010-1011


1015-1015: Add comment on feature_flags semantics
feature_flags (tag 27) is aligned with server PR 10987. Please add a one-line comment in aioesphomeapi/api.proto:

uint32 feature_flags = 27; // Bitmask of climate capabilities (see ClimateFeature enum for bit values)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 696c767 and b200aef.

📒 Files selected for processing (1)
  • aioesphomeapi/api.proto (3 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**

⚙️ CodeRabbit configuration file

  • Do not generate or add any sequence diagrams

Files:

  • aioesphomeapi/api.proto
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: py 3.12 on windows-latest (skip_cython)

@bdraco bdraco added the major label Oct 15, 2025
@bdraco bdraco merged commit 1f5b466 into esphome:main Oct 15, 2025
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants