Skip to content

[API] Sub devices and areas #1146

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 35 commits into from
Jun 22, 2025
Merged

[API] Sub devices and areas #1146

merged 35 commits into from
Jun 22, 2025

Conversation

dala318
Copy link
Contributor

@dala318 dala318 commented Apr 10, 2025

What does this implement/fix?

Adds the possibility to group entities on one physical device into virtual devices (in Home Assistant), handy when one ESP serves several purposes.

Read more in related ESP Home PR

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):

Pull request in esphome (if applicable):

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).

Copy link

codecov bot commented Apr 10, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 100.00%. Comparing base (bd4b664) to head (0e66e85).
Report is 2 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##              main     #1146   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           20        20           
  Lines         2936      2965   +29     
=========================================
+ Hits          2936      2965   +29     

☔ 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.

Copy link

codspeed-hq bot commented Apr 10, 2025

CodSpeed Performance Report

Merging #1146 will not alter performance

Comparing dala318:multi_device (0e66e85) with main (bd4b664)

Summary

✅ 11 untouched benchmarks

@dala318 dala318 marked this pull request as draft April 10, 2025 10:51
Copy link
Contributor

coderabbitai bot commented Apr 10, 2025

Caution

Review failed

The pull request is closed.

"""

Walkthrough

The changes introduce new protocol buffer message types for area and device metadata, add a device association field to various entity response messages, and extend the Python model layer to support sub-device information and device-entity associations. New tests verify correct conversion of area and sub-device lists and handling of area fields within device info structures.

Changes

File(s) Change Summary
aioesphomeapi/api.proto Added AreaInfo and DeviceInfo messages; extended DeviceInfoResponse with device and area lists and singular area; added device_id to all entity list response messages.
aioesphomeapi/model.py Added AreaInfo and SubDeviceInfo dataclasses with conversion methods; added devices, areas, and area to DeviceInfo; added device_id to EntityInfo.
tests/test_model.py Added tests for list conversion and field handling of AreaInfo and SubDeviceInfo within DeviceInfo and entity info classes.

Sequence Diagram(s)

sequenceDiagram
    participant APIClient
    participant ESPHomeDevice
    participant HomeAssistant

    APIClient->>ESPHomeDevice: Request DeviceInfoResponse
    ESPHomeDevice-->>APIClient: DeviceInfoResponse (devices, areas, area, ...)
    APIClient->>HomeAssistant: Register devices and areas
    loop For each entity type
        APIClient->>ESPHomeDevice: Request ListEntities<Type>Response
        ESPHomeDevice-->>APIClient: ListEntities<Type>Response (device_id, ...)
        APIClient->>HomeAssistant: Associate entity with device via device_id
    end
Loading

Assessment against linked issues

Objective Addressed Explanation
Support multiple devices in one config, with device registry improvements (#1335)
Allow entities to be linked to specific devices instead of a single espressif device (#1335)
Provide device and area metadata for Home Assistant integration (#1335)
Enable correct deserialization and model conversion for device/entity associations (#1335)

Assessment against linked issues: Out-of-scope changes

No out-of-scope changes found.
"""


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e7c321f and 0e66e85.

📒 Files selected for processing (1)
  • tests/test_model.py (7 hunks)
✨ Finishing Touches
  • 📝 Generate Docstrings

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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/model.py (1)

220-221: Consider implementing device_id at the EntityInfo base class level.

The commented-out code suggests a plan to add device_id to the base EntityInfo class. This would be a more maintainable approach than adding it to each entity type individually.

-  # # Is it ok to ad for the generic device info before all are added?
-  # device_id: str = ""
+  device_id: str = ""

Since this is marked as a comment/question, please clarify if there's a specific reason to delay adding this field to the base class. Adding it now would simplify future implementations across all entity types.

aioesphomeapi/api.proto (1)

387-387: Consider implementing device_id for all entity types consistently.

Many entity types have commented-out device_id fields. Consider whether these should be implemented now for consistency, or if there's a specific reason to add them incrementally.

A phased approach is reasonable, but ensure there's a clear plan for adding support to all entity types in subsequent PRs. Document this plan if there are specific prerequisites or dependencies that would benefit from a staged implementation.

Also applies to: 456-457, 546-547, 577-578, 613-614, 777-778, 879-880, 961-962, 1000-1001, 1100-1101, 1136-1137, 1192-1193, 1690-1691, 1734-1735, 1773-1774, 1815-1816, 1860-1861, 1890-1891, 1935-1936, 1974-1975

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2ad8751 and d18cce9.

📒 Files selected for processing (3)
  • .github/workflows/ci.yml (1 hunks)
  • aioesphomeapi/api.proto (24 hunks)
  • aioesphomeapi/model.py (5 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
`**`: - Do not generate or add any sequence diagrams

**: - Do not generate or add any sequence diagrams

  • aioesphomeapi/model.py
  • aioesphomeapi/api.proto
🪛 GitHub Check: codecov/patch
aioesphomeapi/model.py

[warning] 145-146: aioesphomeapi/model.py#L145-L146
Added lines #L145 - L146 were not covered by tests


[warning] 148-148: aioesphomeapi/model.py#L148
Added line #L148 was not covered by tests

🔇 Additional comments (9)
.github/workflows/ci.yml (1)

125-131: Improved error handling output for protobuf file differences.

The added echo statements enhance developer experience by providing clearer debugging information when generated protobuf files differ from expected versions.

aioesphomeapi/model.py (4)

172-174: Added sub_devices list to DeviceInfo class.

This addition enables the representation of multiple virtual devices within a single physical device, which aligns well with the PR objectives.


234-234: Added device_id to BinarySensorInfo.

This enables linking binary sensors to specific sub-devices.


251-251: Added device_id to CoverInfo.

This enables linking covers to specific sub-devices.


136-150:

❓ Verification inconclusive

New SubDeviceInfo class added to support virtual device grouping.

This class implements the data model for sub-devices with identification, name, and location information. Good implementation of the convert_list method for handling different input formats.


🏁 Script executed:

#!/bin/bash
# Check if there are any unit tests for the new SubDeviceInfo class

echo "Checking for unit tests covering SubDeviceInfo class..."
rg "SubDeviceInfo" tests/

Length of output: 146


Attention: Confirm Unit Test Coverage for SubDeviceInfo Class

The implementation of the new SubDeviceInfo class—with its clear data model and the robust convert_list method handling both dictionary and protobuf inputs—is well done. However, our search in the tests directory did not locate any unit tests for this class. Please manually verify whether tests exist in another location or consider adding unit tests to cover its functionality (especially for both from_dict and from_pb conversion paths).

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 145-146: aioesphomeapi/model.py#L145-L146
Added lines #L145 - L146 were not covered by tests


[warning] 148-148: aioesphomeapi/model.py#L148
Added line #L148 was not covered by tests

aioesphomeapi/api.proto (4)

185-189: New SubDeviceInfo message type added.

This protocol buffer message provides the structure for transmitting sub-device information with fields for id, name, and suggested_area.


237-237: Added sub_devices field to DeviceInfoResponse message.

This allows the API to report multiple sub-devices associated with a single physical device.


281-281: Implemented device_id field for binary sensors and covers.

These are the first entity types to fully implement the sub-device association. This implementation correctly links these entity types to the new sub-device structure.

Also applies to: 315-315


1-2007:

❓ Verification inconclusive

Verify compatibility with the linked esphome repository PR.

The PR objectives mention a linked PR to the main esphome repository (esphome/esphome#8544). Ensure these API changes are compatible with the changes in that PR.


🌐 Web query:

What's the current status of esphome/esphome PR #8544?

💡 Result:

The current search results do not provide specific information about the status of esphome/esphome PR #8544. The latest mentions in the provided data refer to releases up to 2025.3.3 and changes in 2024.8.x, but no details about PR #8544 are included.

For the most accurate and up-to-date status, you would need to check the esphome/esphome GitHub repository directly. The provided results do not indicate whether this PR has been merged, closed, or is still under review[3][6].

Citations:


Action: Manually verify compatibility with esphome/esphome#8544

The API changes in this file (aioesphomeapi/api.proto, lines 1–2007) should be checked against the upstream modifications introduced in esphome/esphome PR #8544. Currently, web searches did not return specific status details for that PR. Please ensure that:

  • The updated service definitions and RPC options are fully aligned with the upstream changes.
  • Any removed or replaced code in this API file is compatible with the handling in [API] Sub devices and areas esphome#8544.
  • You cross-check the most recent state of the upstream PR directly on GitHub to confirm compatibility.
🧰 Tools
🪛 Buf (1.47.2)

3-3: import "api_options.proto": file does not exist

(COMPILE)

@bdraco bdraco added the waiting-for-esphome Indicates the PR is waiting for the esphome main repo code approval label Apr 10, 2025
@dala318 dala318 marked this pull request as ready for review May 26, 2025 14:09
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 (3)
.github/workflows/ci.yml (1)

127-135: Fix typo in artifact name.

There's a typo in the artifact name that should be corrected.

-          name: genrated-proto-files
+          name: generated-proto-files
aioesphomeapi/api.proto (2)

191-195: Add new SubDeviceInfo message
The SubDeviceInfo message cleanly encapsulates UID, name, and suggested area for sub-devices. To improve maintainability, consider adding a brief proto-doc comment above the message to explain the intended use of each field.


246-247: Embed sub-device list into DeviceInfoResponse
Great addition of repeated SubDeviceInfo sub_devices = 20; to enable virtual device grouping. Please verify that your Python client’s model.py and accompanying tests have been updated to deserialize this new field correctly.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d18cce9 and dc6c005.

📒 Files selected for processing (4)
  • .github/workflows/ci.yml (1 hunks)
  • aioesphomeapi/api.proto (24 hunks)
  • aioesphomeapi/model.py (3 hunks)
  • tests/test_model.py (3 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
`**`: - Do not generate or add any sequence diagrams

**: - Do not generate or add any sequence diagrams

  • tests/test_model.py
  • aioesphomeapi/model.py
  • aioesphomeapi/api.proto
🔇 Additional comments (25)
.github/workflows/ci.yml (1)

127-135: Good addition for debugging protobuf mismatches!

These debugging steps will help identify the exact differences when protobuf files don't match the expected output, making it easier to resolve CI failures.

aioesphomeapi/model.py (1)

137-152: Well-implemented sub-device support!

The implementation correctly adds sub-device support with:

  • A proper SubDeviceInfo class with appropriate fields and conversion logic
  • Clean integration into DeviceInfo using converter fields
  • Addition of device_uid to EntityInfo for device-entity linkage

The code follows the existing patterns in the codebase and handles both dictionary and protobuf conversions appropriately.

Also applies to: 174-176, 222-222

tests/test_model.py (1)

702-739: Comprehensive test coverage for SubDeviceInfo conversion!

The test properly validates the list conversion functionality by:

  • Testing mixed input types (both SubDeviceInfo objects and dictionaries)
  • Verifying correct conversion to SubDeviceInfoModel instances
  • Following the established testing patterns in the file

Good test coverage for the new feature.

aioesphomeapi/api.proto (22)

290-291: Expose device_uid in binary sensor listing
Adding uint32 device_uid = 10; to ListEntitiesBinarySensorResponse makes it possible to map sensors back to their parent devices. This is an additive change and non-breaking.


324-325: Expose device_uid in cover listing
The new device_uid field here will let clients associate covers with sub-devices correctly. Field number 13 aligns sequentially.


396-397: Expose device_uid in fan listing
Inclusion of uint32 device_uid = 13; is consistent with other entity messages and non-breaking.


478-479: Expose device_uid in light listing
The device_uid = 16; field integrates seamlessly. Good to see uniform support across all entity types.


569-570: Expose device_uid in sensor listing
uint32 device_uid = 14; is correctly placed and aids in entity-to-device resolution.


600-601: Expose device_uid in switch listing
device_uid = 10; follows device_class—this will streamline device lookups.


636-637: Expose device_uid in text sensor listing
With uint32 device_uid = 9;, clients can now map text sensors accurately.


817-818: Expose device_uid in camera listing
The device_uid = 8; field is a logical extension to link camera entities to their sub-device.


919-920: Expose device_uid in climate listing
Adding uint32 device_uid = 26; completes the pattern for climate entities.


1001-1002: Expose device_uid in number listing
uint32 device_uid = 14; is added correctly, enabling number entities to reference their device.


1040-1041: Expose device_uid in select listing
Field device_uid = 9; is in place and non-breaking.


1142-1143: Expose device_uid in lock listing
uint32 device_uid = 12; will help clients identify which lock belongs to which sub-device.


1180-1181: Expose device_uid in button listing
Inclusion of device_uid = 9; for buttons is consistent with the new feature scope.


1236-1237: Expose device_uid in media player listing
uint32 device_uid = 10; aligns with other list responses.


1774-1775: Expose device_uid in alarm control panel listing
Great—device_uid = 11; will link alarms back to the correct device.


1818-1819: Expose device_uid in text listing
uint32 device_uid = 12; extends device mapping to generic text entities.


1857-1858: Expose device_uid in date listing
device_uid = 8; is now available for date pickers.


1899-1900: Expose device_uid in time listing
Adding uint32 device_uid = 8; ensures consistency across datetime entities.


1944-1945: Expose device_uid in event listing
device_uid = 10; looks correct and is non-breaking.


1974-1975: Expose device_uid in valve listing
uint32 device_uid = 12; completes entity-to-device linkage for valves.


2019-2020: Expose device_uid in datetime listing
device_uid = 8; is properly placed for DateTime entities.


2058-2059: Expose device_uid in update listing
Adding uint32 device_uid = 9; extends sub-device support to update entities as well.

@bdraco
Copy link
Member

bdraco commented Jun 22, 2025

merged the new api.proto, but we really should fix #1218 before we do a new release

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)

251-253: Extend DeviceInfoResponse with devices, areas, and top-level area
Adding repeated DeviceInfo devices, repeated AreaInfo areas, and the singular AreaInfo area aligns with the sub-device grouping feature.

Consider marking the legacy suggested_area = 16 as deprecated ([deprecated = true]) to guide clients toward the new area field and prevent silent drift.

Also applies to: 255-255


300-300: Add device_id to ListEntities responses
Each ListEntities…Response now includes a uint32 device_id field at the end to associate entities with their physical device. Field numbers correctly follow existing sequences with no collisions.

Don’t forget to regenerate all language bindings (Python models, stubs) and update the public API documentation/changelog to surface these new fields to integrators.

Also applies to: 336-336, 410-410, 494-494, 587-587, 621-621, 659-659, 842-842, 945-945, 1029-1029, 1070-1070, 1113-1113, 1177-1177, 1217-1217, 1273-1273, 1815-1815, 1901-1901, 1946-1946, 1993-1993, 2025-2025, 2072-2072, 2113-2113

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dc6c005 and fb7167c.

📒 Files selected for processing (2)
  • aioesphomeapi/api.proto (25 hunks)
  • aioesphomeapi/model.py (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • aioesphomeapi/model.py
🧰 Additional context used
📓 Path-based instructions (1)
`**`: - Do not generate or add any sequence diagrams

**: - Do not generate or add any sequence diagrams

  • aioesphomeapi/api.proto
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Run benchmarks
🔇 Additional comments (2)
aioesphomeapi/api.proto (2)

191-194: Define new AreaInfo for grouping sub-devices
The AreaInfo message cleanly encapsulates an area’s ID and name. Field numbers are sequenced correctly.


196-200: Define new DeviceInfo for grouping metadata
The DeviceInfo message correctly associates a device_id with its name and parent area_id. Numbering is consistent and non-conflicting.

@bdraco bdraco added minor and removed waiting-for-esphome Indicates the PR is waiting for the esphome main repo code approval labels Jun 22, 2025
@bdraco bdraco changed the title [API] Sub devices [API] Sub devices and areas Jun 22, 2025
@bdraco bdraco merged commit 1ddc6ea into esphome:main Jun 22, 2025
19 of 20 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.

Improve HA device registry and support multiple devices in one config
2 participants