Skip to content

Multiple heating system circuit support#165992

Open
liudger wants to merge 11 commits intohome-assistant:devfrom
liudger:dual-system-support
Open

Multiple heating system circuit support#165992
liudger wants to merge 11 commits intohome-assistant:devfrom
liudger:dual-system-support

Conversation

@liudger
Copy link
Contributor

@liudger liudger commented Mar 19, 2026

Breaking change

Proposed change

This pull request introduces multi-circuit (multi-zone) support for the BSBLan integration in Home Assistant, allowing each heating circuit to be represented as a separate sub-device and entity. The changes refactor the data model, entity structure, and setup logic to support multiple circuits and improve device/sub-device registration and diagnostics. Additionally, the code now registers the main device and sub-devices in the device registry, and updates the quality scale documentation to reflect the new device model.

Multi-circuit support and entity refactoring:

  • The data model is refactored so that BSBLanData and related coordinators handle multiple heating circuits, storing per-circuit state and static data in dictionaries keyed by circuit number. Entities such as climate devices are now created per circuit, using a new BSBLanCircuitEntity base class for sub-device handling. (homeassistant/components/bsblan/__init__.py [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13]

  • The climate platform now creates one entity per available circuit, with unique IDs and device info reflecting the circuit number. Access to state, target temperature, and HVAC mode/action is now circuit-specific. (homeassistant/components/bsblan/climate.py [1] [2] [3] [4]

Device registry and sub-device registration:

  • The integration now registers the main BSB-LAN device in the device registry before forwarding platforms, and each circuit and the water heater as sub-devices using the new entity base classes. This enables proper device relationships and improved device info in the UI. (homeassistant/components/bsblan/__init__.py [1] homeassistant/components/bsblan/entity.py [2] [3] [4]

Diagnostics and configuration improvements:

Documentation and quality scale:

  • The quality scale YAML is updated to reflect that devices and sub-devices are determined at config entry setup, and the exemption for "entity-disabled-by-default" is removed as all entities are now explicitly handled. (homeassistant/components/bsblan/quality_scale.yaml [1] [2]

Type of change

  • Dependency upgrade
  • Bugfix (non-breaking change which fixes an issue)
  • New integration (thank you!)
  • New feature (which adds functionality to an existing integration)
  • Deprecation (breaking change to happen in the future)
  • Breaking change (fix/feature causing existing functionality to break)
  • Code quality improvements to existing code or addition of tests

Additional information

Checklist

  • I understand the code I am submitting and can explain how it works.
  • The code change is tested and works locally.
  • Local tests pass. Your PR cannot be merged unless tests pass
  • There is no commented out code in this PR.
  • I have followed the development checklist
  • I have followed the perfect PR recommendations
  • The code has been formatted using Ruff (ruff format homeassistant tests)
  • Tests have been added to verify that the new code works.
  • Any generated code has been carefully reviewed for correctness and compliance with project standards.

If user exposed functionality or configuration variables are added/changed:

If the code communicates with devices, web services, or third-party tools:

  • The manifest file has all fields filled out correctly.
    Updated and included derived files by running: python3 -m script.hassfest.
  • New or updated dependencies have been added to requirements_all.txt.
    Updated by running python3 -m script.gen_requirements_all.
  • For the updated dependencies a diff between library versions and ideally a link to the changelog/release notes is added to the PR description.

To help with the load of incoming pull requests:

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds multi-heating-circuit support to the bsblan integration by discovering/selecting circuits during config flows, storing state/static data per circuit, and creating separate climate entities per enabled circuit (plus sub-device metadata updates).

Changes:

  • Extend config & reconfigure flows to discover circuits and let users select enabled circuits.
  • Refactor coordinator/data model to store per-circuit State/StaticState, and update climate to create one entity per circuit.
  • Update device/entity translations, diagnostics output, and tests/snapshots to match new entity/device structure.

Reviewed changes

Copilot reviewed 17 out of 17 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tests/components/bsblan/test_water_heater.py Updates expected water heater entity_id and error message matching.
tests/components/bsblan/test_config_flow.py Adds multi-circuit config/reconfigure flow test coverage and updates expected entry data.
tests/components/bsblan/test_climate.py Updates entity_id expectations, service-call assertions to include circuit, and adds dual-circuit entity test.
tests/components/bsblan/snapshots/test_water_heater.ambr Updates snapshots for new water heater entity_id and translated name.
tests/components/bsblan/snapshots/test_diagnostics.ambr Updates diagnostics snapshot structure for per-circuit state/static plus available circuits.
tests/components/bsblan/snapshots/test_climate.ambr Updates climate snapshots for new entity_id and translated naming.
tests/components/bsblan/conftest.py Adds dual-circuit config entry fixture and defaults circuit discovery mock to [1].
homeassistant/components/bsblan/water_heater.py Moves water heater to a sub-device entity base class for device registry structure.
homeassistant/components/bsblan/strings.json Adds circuit selection step strings and device/entity translation keys for circuits/water heater.
homeassistant/components/bsblan/quality_scale.yaml Updates quality-scale statements to reflect sub-device behavior and marks entity-disabled-by-default as done.
homeassistant/components/bsblan/entity.py Introduces circuit/water-heater sub-device entity bases and centralizes main DeviceInfo creation.
homeassistant/components/bsblan/diagnostics.py Emits per-circuit state/static structures and includes available_circuits.
homeassistant/components/bsblan/coordinator.py Changes fast data model to states: dict[int, State] and fetches per-circuit state.
homeassistant/components/bsblan/const.py Adds CONF_HEATING_CIRCUITS.
homeassistant/components/bsblan/config_flow.py Adds circuit discovery and selection steps (initial + reconfigure) and stores selected circuits in entry data.
homeassistant/components/bsblan/climate.py Creates one climate entity per circuit and passes circuit= to thermostat calls.
homeassistant/components/bsblan/init.py Stores per-circuit static data, persists selected circuits in runtime_data, and registers main device early for via_device links.

You can also share your feedback on Copilot code review. Take the survey.

Copilot AI review requested due to automatic review settings March 19, 2026 10:53
@liudger liudger force-pushed the dual-system-support branch from 5a0f091 to 345bf99 Compare March 19, 2026 10:53
Copy link
Contributor

Copilot AI left a comment

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 extends the bsblan integration to support multiple heating circuits by polling and storing per-circuit state/static data and creating one climate entity per discovered circuit, while also introducing sub-devices in the device registry for circuits and the water heater.

Changes:

  • Refactor fast coordinator + runtime data to handle multiple heating-circuit states and per-circuit static values.
  • Create one climate entity per discovered circuit and route service calls with the correct circuit=... parameter.
  • Register sub-devices (heating circuits, water heater) and update diagnostics/tests/snapshots to match the new data shape and naming.

Reviewed changes

Copilot reviewed 17 out of 17 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
homeassistant/components/bsblan/init.py Discover circuits at setup, fetch per-circuit static values, register main device early, store circuits/static in runtime data
homeassistant/components/bsblan/coordinator.py Change fast data from single state to states dict keyed by circuit; poll each circuit sequentially
homeassistant/components/bsblan/climate.py Create one climate entity per circuit; read/write per-circuit state and pass circuit to API calls
homeassistant/components/bsblan/entity.py Introduce circuit + water-heater sub-device entity base classes using via_device + translation_key
homeassistant/components/bsblan/water_heater.py Move water heater entity onto the water-heater sub-device base class
homeassistant/components/bsblan/config_flow.py Bump minor version, store client reference, and change entry title to a constant
homeassistant/components/bsblan/diagnostics.py Update diagnostics payload to include per-circuit states/static and available circuits
homeassistant/components/bsblan/strings.json Add device/entity naming translations for heating circuits and water heater
homeassistant/components/bsblan/quality_scale.yaml Update quality-scale assertions for dynamic/stale devices and entity-disabled-by-default
tests/components/bsblan/conftest.py Add dual-circuit config entry fixture; default get_available_circuits mock
tests/components/bsblan/test_climate.py Update entity id expectations and thermostat call assertions; add dual-circuit entity creation test
tests/components/bsblan/test_config_flow.py Update expected config entry title
tests/components/bsblan/test_init.py Add test verifying discovery-error fallback to single circuit
tests/components/bsblan/test_water_heater.py Update entity id and error regex expectations
tests/components/bsblan/snapshots/test_climate.ambr Snapshot updates for new climate entity id/name
tests/components/bsblan/snapshots/test_water_heater.ambr Snapshot updates for new water heater entity id/name
tests/components/bsblan/snapshots/test_diagnostics.ambr Snapshot updates for per-circuit diagnostics structure
Comments suppressed due to low confidence (1)

homeassistant/components/bsblan/config_flow.py:328

  • Config entry title is hard-coded to "BSB-LAN", which will make multiple configured devices indistinguishable in the UI. Consider using a unique, user-friendly title (e.g., the device-reported name plus a short MAC/host suffix) and keep the hard-coded string only as a fallback if no identifying info is available.
    def _async_create_entry(self) -> ConfigFlowResult:
        """Create the config entry."""
        return self.async_create_entry(
            title="BSB-LAN",
            data={
                CONF_HOST: self.host,
                CONF_PORT: self.port,
                CONF_PASSKEY: self.passkey,
                CONF_USERNAME: self.username,
                CONF_PASSWORD: self.password,
            },

You can also share your feedback on Copilot code review. Take the survey.

liudger added 8 commits March 20, 2026 07:26
- Change config entry title from formatted MAC to 'BSB-LAN'
- Bump config flow MINOR_VERSION to 2
- Store BSBLAN client reference on flow handler for reuse
- Update test assertions for new entry title
- Move DeviceInfo construction to get_bsblan_device_info() in __init__.py
- Use device.name instead of MAC in device name (follows platinum patterns)
- Register main device before forwarding platforms
- Add BSBLanCircuitEntity for heating circuit sub-devices
- Add BSBLanWaterHeaterDeviceEntity for water heater sub-device
- Auto-discover available circuits via get_available_circuits() at setup
- Fetch per-circuit static values during setup
- Pass discovered circuits to fast coordinator
- Coordinator fetches state per circuit sequentially (serial bus)
- BSBLanFastData.state replaced with states: dict[int, State]
- Climate entity created per discovered circuit
- Use BSBLanCircuitEntity base for circuit sub-devices
- Backward compatible unique IDs (circuit 1 keeps old format)
- Pass circuit parameter to thermostat API calls
- Water heater uses BSBLanWaterHeaterDeviceEntity for sub-device
- Diagnostics outputs per-circuit states and static values
- Include available_circuits in diagnostics output
- Add device translations for heating circuits and water heater
- Add climate entity translations per circuit
- Update quality scale: dynamic-devices and stale-devices comments
- Mark entity-disabled-by-default as done
- Add dual-circuit config entry fixture and mock setup
- Update climate tests for per-circuit entity creation
- Add test for circuit discovery error fallback
- Update diagnostics, water heater, and climate snapshots
- Mock get_available_circuits in conftest
Copilot AI review requested due to automatic review settings March 20, 2026 07:36
@liudger liudger force-pushed the dual-system-support branch from ca8a2fb to 363e0fd Compare March 20, 2026 07:36
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds multi-circuit (multi-zone) support to the BSBLan integration by restructuring coordinator data to be circuit-keyed, introducing sub-device modeling for heating circuits and DHW, and updating platforms/diagnostics/tests accordingly.

Changes:

  • Discover available heating circuits at config-entry setup, fetch per-circuit static values, and poll per-circuit fast “state” data.
  • Model heating circuits and DHW as sub-devices (via DeviceInfo.via_device) and create one climate entity per circuit.
  • Update diagnostics output and expand tests/snapshots to reflect multi-circuit state/static structures and new entity IDs/names.

Reviewed changes

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

Show a summary per file
File Description
homeassistant/components/bsblan/init.py Adds circuit discovery, per-circuit static fetching, passes circuits into the fast coordinator, and registers the main device up-front.
homeassistant/components/bsblan/coordinator.py Changes fast coordinator payload from single state to per-circuit states and polls state(..., circuit=...) for each circuit.
homeassistant/components/bsblan/entity.py Introduces sub-device base entities for heating circuits and DHW, using via_device to link to the main device.
homeassistant/components/bsblan/climate.py Creates one climate entity per discovered circuit; routes reads/writes through the circuit-specific state and service calls.
homeassistant/components/bsblan/water_heater.py Switches water heater entity to the new DHW sub-device base entity.
homeassistant/components/bsblan/diagnostics.py Emits per-circuit state/static dictionaries and exposes available_circuits.
homeassistant/components/bsblan/config_flow.py Changes config entry title creation behavior.
homeassistant/components/bsblan/strings.json Adds device/entity translation keys for heating circuits and water heater naming.
homeassistant/components/bsblan/quality_scale.yaml Updates quality-scale statements to reflect multi-device/sub-device modeling.
tests/components/bsblan/conftest.py Adds a dual-circuit config entry fixture; sets default available circuits in the mock client.
tests/components/bsblan/test_climate.py Updates entity IDs and asserts circuit is passed to thermostat calls; adds a dual-circuit entity existence test.
tests/components/bsblan/test_water_heater.py Updates expected water heater entity ID and error message match.
tests/components/bsblan/test_init.py Adds circuit discovery fallback test; updates static fallback assertions for dict-based static storage.
tests/components/bsblan/test_diagnostics.py Updates expectation for dict-shaped per-circuit static output.
tests/components/bsblan/test_config_flow.py Updates expectations for new config entry title behavior.
tests/components/bsblan/snapshots/test_climate.ambr Updates snapshots for new entity ID and friendly name.
tests/components/bsblan/snapshots/test_water_heater.ambr Updates snapshots for new entity ID and friendly name.
tests/components/bsblan/snapshots/test_diagnostics.ambr Updates snapshots for per-circuit states/static and available_circuits.
Comments suppressed due to low confidence (1)

homeassistant/components/bsblan/config_flow.py:326

  • async_create_entry now uses a constant title ("BSB-LAN"). Since the integration allows multiple config entries, this will make entries indistinguishable in the UI. Consider including something stable but differentiating (e.g., device name, host, or MAC) in the title while still keeping migrations/backward compatibility in mind.
    def _async_create_entry(self) -> ConfigFlowResult:
        """Create the config entry."""
        return self.async_create_entry(
            title="BSB-LAN",
            data={
                CONF_HOST: self.host,
                CONF_PORT: self.port,
                CONF_PASSKEY: self.passkey,
                CONF_USERNAME: self.username,
                CONF_PASSWORD: self.password,
            },

@liudger liudger changed the title Dual heating system circuit support Multiple heating system circuit support Mar 20, 2026
@liudger liudger marked this pull request as ready for review March 20, 2026 08:18
Copilot AI review requested due to automatic review settings March 20, 2026 08:18
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 18 out of 18 changed files in this pull request and generated 3 comments.

Comments suppressed due to low confidence (1)

homeassistant/components/bsblan/water_heater.py:66

  • Similar to the climate entity, the water heater entity has _attr_name = None but no _attr_translation_key/_attr_suggested_object_id, so the default entity_id ends up being derived from the translated device name (e.g., water_heater.water_heater) and can become locale-dependent. Consider setting a stable suggested object id / translation key for the entity so new installs get a deterministic entity_id while keeping the existing unique_id for backward compatibility.
class BSBLANWaterHeater(BSBLanWaterHeaterDeviceEntity, WaterHeaterEntity):
    """Defines a BSBLAN water heater entity."""

    _attr_name = None
    _attr_operation_list = list(HA_TO_BSBLAN_OPERATION_MODE.keys())

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants