Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@Alexwijn
Copy link
Owner

@Alexwijn Alexwijn commented Feb 16, 2025

Summary by CodeRabbit

  • New Features

    • Services to reset PID integral and to enable/disable Pulse Width Modulation for climate devices.
    • Added project funding/support links.
  • Improvements

    • More detailed boiler status and refined temperature tracking.
    • Cleaner PWM and relative-modulation behavior with improved cycle/setpoint handling.
    • Manufacturer names shown as friendlier labels.
    • Configuration flow skips extra steps in simulator mode.
  • Documentation

    • Updated translations and README guidance.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 16, 2025

Warning

Rate limit exceeded

@Alexwijn has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 0 minutes and 59 seconds before requesting another review.

βŒ› How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 03dcdae and 4caaf47.

πŸ“’ Files selected for processing (1)
  • README.md (8 hunks)

Walkthrough

Refactors manufacturer handling (rename name→friendly_name, Manufacturer → ABC), replaces DeviceStatus with BoilerStatus, reworks PWM API (new Cycles, changed signatures), adds services reset_integral and pulse_width_modulation, renames support flags to supports_relative_modulation, updates constants, translations, and funding info.

Changes

Cohort / File(s) Change Summary
Repo metadata
​.github/FUNDING.yml
Added GitHub sponsor Alexwijn and buy_me_a_coffee: alexwijn.
Integration setup & services
custom_components/sat/__init__.py, custom_components/sat/services.py, custom_components/sat/services.yaml, custom_components/sat/translations/en.json, custom_components/sat/translations/sk.json
Added OPTIONS_DEFAULTS, SERVICE_RESET_INTEGRAL, SERVICE_PULSE_WIDTH_MODULATION; register services at setup; implemented reset_integral and pulse_width_modulation; removed clear_integral; added translations.
PWM & util
custom_components/sat/pwm.py, custom_components/sat/util.py
Added Cycles class; PWM now accepts Cycles, exposes setpoint property, reordered update args; create_pwm_controller signature updated to accept support flag and builds Cycles; added get_climate_entities.
Boiler / Coordinator / Climate
custom_components/sat/boiler.py, custom_components/sat/coordinator.py, custom_components/sat/climate.py
Replaced DeviceStatus with BoilerStatus enum; extended boiler state with device_status and flame_on_since; adjusted temperature-tracking comparisons and PWM/setpoint usage.
Manufacturer refactor
custom_components/sat/manufacturer.py, custom_components/sat/manufacturers/*, tests/test_manufacturer.py
Made Manufacturer an ABC; simplified MANUFACTURERS mapping; renamed name→friendly_name across manufacturers; added/removed manufacturer classes; updated tests to assert friendly_name/member_id.
Entity display / sensors
custom_components/sat/entity.py, custom_components/sat/sensor.py
Use manufacturer.friendly_name for device info and manufacturer sensor native value instead of .name.
Relative modulation & coordinators
custom_components/sat/binary_sensor.py, custom_components/sat/esphome/__init__.py, custom_components/sat/fake/__init__.py, custom_components/sat/mqtt/ems.py, custom_components/sat/mqtt/opentherm.py, custom_components/sat/serial/__init__.py, custom_components/sat/simulator/__init__.py
Renamed property supports_relative_modulation_management β†’ supports_relative_modulation; added passthrough in fake coordinator; updated checks across coordinators and MQTT/serial drivers.
Area / Overshoot protection / Relative modulation / Docs
custom_components/sat/area.py, custom_components/sat/overshoot_protection.py, custom_components/sat/relative_modulation.py, README.md
Removed PWM instantiation from Area; renamed MINIMUM_RELATIVE_MOD/MAXIMUM_RELATIVE_MOD β†’ *_MODULATION and updated usages; simplified relative modulation state logic; README edits.
Tests & translations
tests/test_manufacturer.py, custom_components/sat/translations/sk.json
Updated manufacturer tests to reflect friendly_name/member_id semantics; added Slovak translations for new services and UI keys.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant U as User
    participant HA as Home Assistant
    participant S as sat.services
    participant ER as EntityRegistry
    participant E as SatClimate
    U->>HA: Call service (reset_integral / pulse_width_modulation)
    HA->>S: dispatch to integration service handler
    S->>ER: resolve target entity IDs
    ER-->>S: list of SatClimate entities
    S->>E: call reset_integral() / set_pwm(enabled)
    E-->>S: ack
    S-->>HA: service complete
    HA-->>U: return result
Loading
sequenceDiagram
    autonumber
    participant User
    participant Flow as SatFlowHandler
    participant Finish as async_step_finish
    User->>Flow: Start config flow (mode=SIMULATOR)
    Flow->>Flow: detect MODE_SIMULATOR
    Flow->>Finish: call async_step_finish()
    Finish-->>Flow: finish result
    Flow-->>User: flow completed
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
βœ… Passed checks (2 passed)
Check name Status Explanation
Description Check βœ… Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check βœ… Passed The pull request title "Boiler and PWM improvements" is directly related to substantive changes throughout the codebase. The raw summary documents extensive modifications to boiler state management, including a new BoilerStatus enum, updated BoilerState constructor with new parameters (device_status, flame_on_since), and new properties. Similarly, the PWM controller undergoes significant improvements, including a new Cycles class, restructured constructor parameters, updated parameter ordering in the update method, and new setpoint management logic. The title accurately captures these two primary improvement areas. While the PR also includes broader refactoring work such as manufacturer class restructuring, constant renames, and new service additions, the boiler and PWM improvements represent the core functional enhancements and are clearly present and significant in the changeset.

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.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 16, 2025

βœ… 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.

@coderabbitai coderabbitai bot changed the title @coderabbitai Update SAT integration: endpoints, boiler, PWM, and simulator support Feb 16, 2025
@Alexwijn Alexwijn changed the title Update SAT integration: endpoints, boiler, PWM, and simulator support Boiler and PWM improvements Feb 16, 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: 3

🧹 Nitpick comments (9)
custom_components/sat/pwm.py (1)

66-66: Potential type mismatch in _setpoint_offset.

The annotation declares _setpoint_offset: int, but it is sometimes assigned a float value (0.5).
Consider updating the type annotation to float or using an integer to avoid confusion and improve type consistency.

- self._setpoint_offset: int = 0.5 if supports_relative_modulation_management else 1
+ self._setpoint_offset: float = 0.5 if supports_relative_modulation_management else 1
custom_components/sat/coordinator.py (1)

334-337: Simplify return logic.

These blocks return False if isinstance(...), otherwise True. Inline the negation to eliminate the explicit if-else.
Although minor, this makes the code shorter and more readable:

-if isinstance(self.manufacturer, (Ideal, Intergas, Geminox, Nefit)):
-    return False
-return True
+return not isinstance(self.manufacturer, (Ideal, Intergas, Geminox, Nefit))

Also applies to: 346-349

🧰 Tools
πŸͺ› Ruff (0.8.2)

334-337: Return the negated condition directly

Inline condition

(SIM103)

custom_components/sat/services.py (2)

14-29: Add error handling for the reset operation.

Consider adding try-catch blocks to handle potential errors during the reset operation and log any failures.

Apply this diff to add error handling:

 async def reset_integral(call: ServiceCall):
     """Service to reset the integral part of the PID controller."""
     target_entities = call.data.get("entity_id", [])

     for climate in get_climate_entities(hass, target_entities):
         _LOGGER.info("Reset Integral action called for %s", climate.entity_id)

+        try:
             climate.pid.reset()
             climate.areas.pids.reset()
+        except Exception as e:
+            _LOGGER.error("Failed to reset integral for %s: %s", climate.entity_id, str(e))

31-49: Add error handling and state validation.

Consider adding:

  1. Try-catch blocks to handle potential errors during enable/disable operations
  2. State validation to prevent redundant operations

Apply this diff to add error handling and state validation:

 async def pulse_width_modulation(call: ServiceCall):
     """Service to enable or disable Pulse Width Modulation."""
     enabled = call.data.get("enabled")
     target_entities = call.data.get("entity_id", [])

     for climate in get_climate_entities(hass, target_entities):
         _LOGGER.info("Pulse Width Modulation action called for %s with enabled=%s", climate.entity_id, enabled)

+        try:
+            # Skip if already in desired state
+            if enabled == climate.pwm.is_enabled():
+                _LOGGER.debug("PWM already in desired state for %s", climate.entity_id)
+                continue
+
             if enabled:
                 climate.pwm.enable()
             else:
                 climate.pwm.disable()
+        except Exception as e:
+            _LOGGER.error("Failed to set PWM state for %s: %s", climate.entity_id, str(e))
custom_components/sat/fake/__init__.py (1)

93-95: Consider removing this pass-through property in a future update.

The property supports_relative_modulation simply returns supports_relative_modulation_management. While this is likely part of a transition to rename the property across the codebase, consider removing this pass-through property in a future update once all references have been updated to use supports_relative_modulation directly.

custom_components/sat/util.py (2)

71-83: Consider replacing star imports with explicit imports.

The function changes look good, but there are several constants imported with star imports that could be made explicit for better maintainability.

Replace star imports with explicit imports:

-from .const import *
+from .const import (
+    CONF_CYCLES_PER_HOUR,
+    CONF_AUTOMATIC_DUTY_CYCLE,
+    CONF_DUTY_CYCLE,
+    CONF_MODE,
+    MODE_SWITCH,
+    CONF_FORCE_PULSE_WIDTH_MODULATION,
+)
🧰 Tools
πŸͺ› Ruff (0.8.2)

74-74: CONF_CYCLES_PER_HOUR may be undefined, or defined from star imports

(F405)


75-75: CONF_AUTOMATIC_DUTY_CYCLE may be undefined, or defined from star imports

(F405)


76-76: CONF_DUTY_CYCLE may be undefined, or defined from star imports

(F405)


77-77: CONF_MODE may be undefined, or defined from star imports

(F405)


77-77: MODE_SWITCH may be undefined, or defined from star imports

(F405)


77-77: CONF_FORCE_PULSE_WIDTH_MODULATION may be undefined, or defined from star imports

(F405)


86-103: Consider replacing star imports with explicit imports.

The function implementation looks good, but there are constants imported with star imports that could be made explicit for better maintainability.

Replace star imports with explicit imports:

-from .const import *
+from .const import DOMAIN, CLIMATE
🧰 Tools
πŸͺ› Ruff (0.8.2)

95-95: DOMAIN may be undefined, or defined from star imports

(F405)


98-98: CLIMATE may be undefined, or defined from star imports

(F405)

custom_components/sat/services.yaml (1)

1-6: Service 'reset_integral' Definition

The new reset_integral service is added with a target specifying that only climate entities integrated with "sat" will be affected. While the target configuration is correctly defined, consider whether adding an inline description here would improve clarity and consistency with the translations file.

custom_components/sat/translations/en.json (1)

259-268: Translation Entry for 'pulse_width_modulation' Service

The translation entry for pulse_width_modulation is functional; however, the description could be rephrased for improved clarity. For example, consider updating it to:
"Force enable or disable Pulse Width Modulation; note that the PWM state may automatically revert shortly after being set."
This adjustment would help avoid potential confusion about the transient nature of the setting.

πŸ“œ Review details

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

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 3d42ebe and 48443fd.

πŸ“’ Files selected for processing (45)
  • .github/FUNDING.yml (1 hunks)
  • custom_components/sat/__init__.py (2 hunks)
  • custom_components/sat/area.py (0 hunks)
  • custom_components/sat/binary_sensor.py (1 hunks)
  • custom_components/sat/boiler.py (3 hunks)
  • custom_components/sat/climate.py (8 hunks)
  • custom_components/sat/config_flow.py (4 hunks)
  • custom_components/sat/const.py (2 hunks)
  • custom_components/sat/coordinator.py (7 hunks)
  • custom_components/sat/entity.py (1 hunks)
  • custom_components/sat/esphome/__init__.py (1 hunks)
  • custom_components/sat/fake/__init__.py (1 hunks)
  • custom_components/sat/manufacturer.py (1 hunks)
  • custom_components/sat/manufacturers/atag.py (1 hunks)
  • custom_components/sat/manufacturers/baxi.py (1 hunks)
  • custom_components/sat/manufacturers/brotge.py (1 hunks)
  • custom_components/sat/manufacturers/de_dietrich.py (1 hunks)
  • custom_components/sat/manufacturers/ferroli.py (1 hunks)
  • custom_components/sat/manufacturers/geminox.py (1 hunks)
  • custom_components/sat/manufacturers/ideal.py (1 hunks)
  • custom_components/sat/manufacturers/immergas.py (1 hunks)
  • custom_components/sat/manufacturers/intergas.py (1 hunks)
  • custom_components/sat/manufacturers/itho.py (1 hunks)
  • custom_components/sat/manufacturers/nefit.py (1 hunks)
  • custom_components/sat/manufacturers/other.py (1 hunks)
  • custom_components/sat/manufacturers/radiant.py (1 hunks)
  • custom_components/sat/manufacturers/remeha.py (1 hunks)
  • custom_components/sat/manufacturers/sime.py (1 hunks)
  • custom_components/sat/manufacturers/simulator.py (0 hunks)
  • custom_components/sat/manufacturers/vaillant.py (1 hunks)
  • custom_components/sat/manufacturers/viessmann.py (1 hunks)
  • custom_components/sat/manufacturers/worcester.py (1 hunks)
  • custom_components/sat/mqtt/ems.py (1 hunks)
  • custom_components/sat/mqtt/opentherm.py (1 hunks)
  • custom_components/sat/overshoot_protection.py (2 hunks)
  • custom_components/sat/pwm.py (11 hunks)
  • custom_components/sat/relative_modulation.py (1 hunks)
  • custom_components/sat/sensor.py (1 hunks)
  • custom_components/sat/serial/__init__.py (1 hunks)
  • custom_components/sat/services.py (1 hunks)
  • custom_components/sat/services.yaml (1 hunks)
  • custom_components/sat/simulator/__init__.py (1 hunks)
  • custom_components/sat/translations/en.json (1 hunks)
  • custom_components/sat/util.py (2 hunks)
  • tests/test_manufacturer.py (2 hunks)
πŸ’€ Files with no reviewable changes (2)
  • custom_components/sat/manufacturers/simulator.py
  • custom_components/sat/area.py
βœ… Files skipped from review due to trivial changes (14)
  • .github/FUNDING.yml
  • custom_components/sat/manufacturers/sime.py
  • custom_components/sat/manufacturers/brotge.py
  • custom_components/sat/manufacturers/nefit.py
  • custom_components/sat/manufacturers/intergas.py
  • custom_components/sat/manufacturers/de_dietrich.py
  • custom_components/sat/manufacturers/viessmann.py
  • custom_components/sat/manufacturers/atag.py
  • custom_components/sat/mqtt/ems.py
  • custom_components/sat/serial/init.py
  • custom_components/sat/mqtt/opentherm.py
  • custom_components/sat/overshoot_protection.py
  • custom_components/sat/esphome/init.py
  • custom_components/sat/simulator/init.py
🧰 Additional context used
πŸͺ› Ruff (0.8.2)
custom_components/sat/__init__.py

24-24: .const.SERVICE_RESET_INTEGRAL imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


25-25: .const.SERVICE_PULSE_WIDTH_MODULATION imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)


29-29: .util.get_climate_entities imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)

custom_components/sat/util.py

10-10: from .const import * used; unable to detect undefined names

(F403)


74-74: CONF_CYCLES_PER_HOUR may be undefined, or defined from star imports

(F405)


75-75: CONF_AUTOMATIC_DUTY_CYCLE may be undefined, or defined from star imports

(F405)


76-76: CONF_DUTY_CYCLE may be undefined, or defined from star imports

(F405)


77-77: CONF_MODE may be undefined, or defined from star imports

(F405)


77-77: MODE_SWITCH may be undefined, or defined from star imports

(F405)


77-77: CONF_FORCE_PULSE_WIDTH_MODULATION may be undefined, or defined from star imports

(F405)


95-95: DOMAIN may be undefined, or defined from star imports

(F405)


98-98: CLIMATE may be undefined, or defined from star imports

(F405)

custom_components/sat/config_flow.py

357-357: CONF_MODE may be undefined, or defined from star imports

(F405)


357-357: MODE_SIMULATOR may be undefined, or defined from star imports

(F405)


446-446: CONF_MODE may be undefined, or defined from star imports

(F405)


446-446: MODE_SIMULATOR may be undefined, or defined from star imports

(F405)


467-467: CONF_MODE may be undefined, or defined from star imports

(F405)


467-467: MODE_SIMULATOR may be undefined, or defined from star imports

(F405)

custom_components/sat/coordinator.py

14-14: from .const import * used; unable to detect undefined names

(F403)


108-108: MINIMUM_SETPOINT may be undefined, or defined from star imports

(F405)


111-112: Use a single if statement instead of nested if statements

(SIM102)


128-128: DEADBAND may be undefined, or defined from star imports

(F405)


301-301: CONF_MINIMUM_SETPOINT may be undefined, or defined from star imports

(F405)


334-337: Return the negated condition directly

Inline condition

(SIM103)


346-349: Return the negated condition directly

Inline condition

(SIM103)

custom_components/sat/manufacturer.py

46-46: Local variable member_id is assigned to but never used

(F841)

custom_components/sat/climate.py

42-42: from .const import * used; unable to detect undefined names

(F403)


564-564: MINIMUM_RELATIVE_MODULATION may be undefined, or defined from star imports

(F405)

πŸ”‡ Additional comments (38)
custom_components/sat/pwm.py (3)

103-103: Verify the parameter order in update method.

The method signature has changed to async def update(self, boiler: BoilerState, requested_setpoint: float).
If existing call sites rely on the previous parameter order, this will cause breakage.
Please confirm or update all call sites accordingly.


137-143: Double-check logic for adjusted setpoint transitions.

In these lines, _setpoint is either adjusted downward (- _setpoint_offset), set to _setpoint_adjuster.current, or forced to boiler temperature plus 10.
Ensure each transition is thoroughly tested to avoid abrupt or unintended temperature jumps.


269-272: Return fallback setpoint.

Returning self._setpoint or MINIMUM_SETPOINT ensures a valid setpoint even if _setpoint is None.
This is a reasonable fallback, but confirm any edge cases where an uninitialized _setpoint might mask a bug.
Overall, the logic appears appropriate.

custom_components/sat/coordinator.py (2)

103-143: Comprehensive expansion of BoilerStatus.

The newly introduced and refined statuses (INITIALIZING, HOT_WATER, IDLE, etc.) add clarity.
Ensure that any custom logic (e.g., COOLING_DOWN, OVERSHOOT_HANDLING) is covered by appropriate tests and that downstream components handle the new states correctly.

🧰 Tools
πŸͺ› Ruff (0.8.2)

108-108: MINIMUM_SETPOINT may be undefined, or defined from star imports

(F405)


111-112: Use a single if statement instead of nested if statements

(SIM102)


128-128: DEADBAND may be undefined, or defined from star imports

(F405)


298-302: Potential undefined import for CONF_MINIMUM_SETPOINT.

Referencing self._data.get(CONF_MINIMUM_SETPOINT) relies on the star import from .const.
Ensure that CONF_MINIMUM_SETPOINT is always in scope or consider importing explicitly to avoid potential reference issues highlighted by static analysis.

🧰 Tools
πŸͺ› Ruff (0.8.2)

301-301: CONF_MINIMUM_SETPOINT may be undefined, or defined from star imports

(F405)

custom_components/sat/climate.py (3)

563-565: Check definition of MINIMUM_RELATIVE_MODULATION.

Static analysis indicates that MINIMUM_RELATIVE_MODULATION may come from a star import.
Verify that it is indeed defined in .const or elsewhere to prevent runtime NameError.

🧰 Tools
πŸͺ› Ruff (0.8.2)

564-564: MINIMUM_RELATIVE_MODULATION may be undefined, or defined from star imports

(F405)


928-930: Confirm logic for disabling PWM during cooling phase.

Disabling PWM when the system transitions to COOLING_DOWN and the calculated setpoint is higher than pwm.setpoint helps avoid overshoot.
Ensure that any partial or mid-cycle transitions won’t leave the system in an unintended state.


950-959: Sequential checks for dynamic minimum setpoint.

When self._minimum_setpoint_version == 1 and the device is actively heating, the code updates the dynamic minimum setpoint and then toggles heater state depending on _setpoint.
Confirm that timing edge cases (e.g., partial flame cycles or quick toggles) don’t lead to frequent on/off cycling.

🧰 Tools
πŸͺ› Ruff (0.8.2)

959-959: MINIMUM_SETPOINT may be undefined, or defined from star imports

(F405)

custom_components/sat/manufacturers/baxi.py (1)

6-7: LGTM! Consistent with the codebase-wide property renaming.

The renaming from name to friendly_name is well-implemented and maintains the original functionality.

custom_components/sat/manufacturers/ideal.py (1)

6-7: LGTM! Maintains consistency with other manufacturer implementations.

The property renaming is implemented correctly and follows the same pattern as other manufacturer classes.

custom_components/sat/manufacturers/geminox.py (1)

6-7: LGTM! Follows the established pattern for manufacturer classes.

The property renaming is implemented consistently with other manufacturer classes.

custom_components/sat/manufacturers/ferroli.py (1)

6-7:

βœ… Verification successful

LGTM! Consistent implementation across all manufacturer classes.

The property renaming is implemented correctly. Let's verify the impact across the codebase.


🏁 Script executed:

#!/bin/bash
# Description: Verify that all manufacturer classes use the new property name
# and there are no remaining references to the old property name

# Check for any remaining uses of the old property name
echo "Checking for remaining uses of 'def name' in manufacturer classes..."
rg "def name" "custom_components/sat/manufacturers/"

# Check for consistent use of the new property name
echo "Verifying consistent use of 'friendly_name' in manufacturer classes..."
rg "def friendly_name" "custom_components/sat/manufacturers/"

# Check for any remaining references to '.name' in the codebase
echo "Checking for remaining references to '.name' property..."
rg "\.name" "custom_components/sat/"

Length of output: 2149


Approved: Manufacturer Implementation Consistency Confirmed

The update to use friendly_name in manufacturer classes is correctly applied across the board. Our checks confirm that no manufacturer file still declares a name property, and all manufacturer classes (including ferroli.py) consistently implement friendly_name.

  • All manufacturer files now define and use friendly_name (as seen in multiple files including custom_components/sat/manufacturers/ferroli.py).
  • The only remaining reference to .name is in custom_components/sat/switch/__init__.py. If that reference is meant for a different type of entity or is intentional, no further action is needed.

LGTM!

custom_components/sat/manufacturers/itho.py (1)

4-7: LGTM!

The implementation follows the established pattern for manufacturer classes, with proper inheritance, property decoration, and type annotation.

custom_components/sat/manufacturers/radiant.py (1)

6-6: LGTM!

The renaming from name to friendly_name aligns with the broader changes across manufacturer classes while maintaining the same functionality.

custom_components/sat/manufacturers/other.py (1)

4-7: LGTM!

The implementation follows the established pattern for manufacturer classes, with proper inheritance, property decoration, and type annotation.

custom_components/sat/manufacturers/vaillant.py (1)

6-6: LGTM!

The renaming from name to friendly_name aligns with the broader changes across manufacturer classes while maintaining the same functionality.

custom_components/sat/manufacturers/immergas.py (1)

6-7: LGTM!

The renaming of the name property to friendly_name is consistent with the broader refactoring effort to standardize manufacturer naming across the integration.

custom_components/sat/manufacturers/remeha.py (1)

4-7: LGTM!

The new Remeha manufacturer class follows the established pattern and correctly implements the friendly_name property.

custom_components/sat/manufacturers/worcester.py (1)

4-7: LGTM!

The new Worcester manufacturer class follows the established pattern and correctly implements the friendly_name property.

custom_components/sat/entity.py (1)

30-30: LGTM!

The update to use friendly_name instead of name is consistent with the manufacturer class changes while maintaining proper null checks and default values.

tests/test_manufacturer.py (2)

10-10: LGTM!

The assertion correctly verifies that the resolved manufacturer's class name matches the name from MANUFACTURERS.


19-21: LGTM!

The changes improve test coverage by:

  1. Correctly building the member_id_to_names dictionary using the new MANUFACTURERS structure
  2. Adding an additional assertion to verify member_id
  3. Using friendly_name in the assertion message for better clarity

Also applies to: 28-29

custom_components/sat/manufacturer.py (2)

6-25: LGTM!

The simplified MANUFACTURERS dictionary structure improves maintainability by directly mapping manufacturer names to their IDs.


28-39: LGTM!

The changes improve the Manufacturer class by:

  1. Making it an abstract base class
  2. Adding member_id property with proper initialization
  3. Renaming name to friendly_name for better clarity
custom_components/sat/relative_modulation.py (1)

37-43: LGTM!

The changes improve the code by:

  1. Simplifying the control flow
  2. Reducing nested conditions
  3. Making the order of checks more logical and easier to follow
custom_components/sat/util.py (1)

79-80: LGTM! Good use of the Cycles class.

The introduction of the Cycles class to encapsulate cycle-related parameters improves code organization and maintainability.

custom_components/sat/const.py (2)

22-23: LGTM! Good improvement in constant naming.

The renaming from *_MOD to *_MODULATION improves code clarity by using the full word.


169-169: LGTM! Service constant follows naming convention.

The new service constant follows the existing naming pattern and is properly grouped with other service-related constants.

custom_components/sat/boiler.py (4)

10-10: Verify the impact of increased setpoint margin.

The EXCEED_SETPOINT_MARGIN has been increased from 0.1 to 1.0, which could significantly impact temperature tracking behavior. Please ensure this change aligns with the expected boiler behavior.


13-28: LGTM! Well-structured enum for boiler states.

The BoilerStatus enum provides a comprehensive and well-named set of boiler states. Good use of str inheritance for string representation.


35-44: LGTM! Good enhancement of boiler state tracking.

The BoilerState class has been enhanced with proper typing and additional state tracking capabilities through the device_status and flame_on_since parameters.


135-138: LGTM! Improved temperature tracking logic.

The temperature tracking logic has been improved with:

  • Simplified condition for exceeding setpoint
  • Added margin to stabilization check
  • More precise temperature comparisons
custom_components/sat/__init__.py (1)

65-66: LGTM! Service registration added.

The addition of service registration enhances the functionality of the integration.

custom_components/sat/sensor.py (1)

241-241: LGTM! Property renamed for consistency.

The change from name to friendly_name is consistent with the broader property renaming effort across the codebase.

custom_components/sat/config_flow.py (2)

357-359: LGTM! Simulator mode flow optimization.

The changes optimize the configuration flow by bypassing unnecessary steps when in simulator mode, providing a more streamlined user experience.

Also applies to: 446-448, 467-469

🧰 Tools
πŸͺ› Ruff (0.8.2)

357-357: CONF_MODE may be undefined, or defined from star imports

(F405)


357-357: MODE_SIMULATOR may be undefined, or defined from star imports

(F405)


492-492: LGTM! Manufacturer resolution improved.

The changes improve manufacturer resolution by:

  1. Using a default value of -1 when no manufacturers are found
  2. Consistently using friendly_name for manufacturer display

Also applies to: 497-499

custom_components/sat/services.yaml (1)

7-15: Service 'pulse_width_modulation' Definition

The pulse_width_modulation service is defined with the necessary target details and includes a required field enabled with an example value. The YAML structure appears correct and follows standard configuration practices. Optionally, you might want to add an inline description if it isn’t solely provided via translations for clarity.

custom_components/sat/translations/en.json (1)

254-258: Translation Entry for 'reset_integral' Service

The JSON entry for reset_integral includes a clear name and description that appropriately explains its functionality in resetting the integral part of the PID controller. The content is both descriptive and user-friendly.

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 (8)
README.md (8)

244-245: Briefly describe when to choose β€œAdaptive Controller”

Add a one‑line rationale (e.g., default choice vs. special cases) to help users pick among controller types.


246-247: Call out that β€œAutomatic Gains Value” is not used with Adaptive

To avoid confusion, explicitly state that the Automatic Gains control is ignored/disabled when Adaptive is active.

Apply this diff to append the clarification:

 > [!NOTE]
-> When the Adaptive controller is active, SAT automatically tunes the gains. No need for tweaking.
+> When the Adaptive controller is active, SAT automatically tunes the gains. No need for tweaking. The β€œAutomatic Gains Value” setting does not apply when Adaptive is active.

268-268: Fix markdownlint MD049 (emphasis style) and clarify scope

Your linter expects underscores for emphasis. Also reiterate that this control doesn’t apply to Adaptive.

Apply this diff:

-*Automatic Gains Value*: Automatically tweaking the aggressiveness of the Kp, Ki and Kd gains when Classic or Improved Controller is in use.
+_Automatic Gains Value_: Automatically tweaking the aggressiveness of the Kp, Ki and Kd gains when Classic or Improved Controller is in use. Not applicable when the Adaptive Controller is active.

218-219: Typo: β€œRecommented” β†’ β€œRecommended”

Fix spelling in both occurrences for polish.

Apply this diff:

- - [Precision Curve](https://www.desmos.com/calculator/spfvsid4ds) ( Recommented )
+ - [Precision Curve](https://www.desmos.com/calculator/spfvsid4ds) ( Recommended )

223-224: Typo: β€œRecommented” β†’ β€œRecommended”

Same fix here.

Apply this diff:

- - [Precision Curve](https://www.desmos.com/calculator/i7f7uuyaoz) ( Recommented )
+ - [Precision Curve](https://www.desmos.com/calculator/i7f7uuyaoz) ( Recommended )

185-186: Typo: β€œsyncronize” β†’ β€œsynchronize”

Minor copy edit.

Apply this diff:

-   - Primary: Users can add their physical thermostat. SAT will syncronize the `hvac_action` of the physical thermostat with the SAT climate entity's `hvac action`, that means if the physical thermostat doesn't require heating then the SAT climate entity `hvac_action` will remain at idle. Also the physical thermostat's room setpoint stays in sync with SAT climate entity. Moreover the physical thermostat will act as a back up if any failure to HA occurs.
+   - Primary: Users can add their physical thermostat. SAT will synchronize the `hvac_action` of the physical thermostat with the SAT climate entity's `hvac action`, that means if the physical thermostat doesn't require heating then the SAT climate entity `hvac_action` will remain at idle. Also the physical thermostat's room setpoint stays in sync with SAT climate entity. Moreover the physical thermostat will act as a back up if any failure to HA occurs.

187-188: Standardize callout casing

Use a consistent β€œ[!NOTE]” (all‑caps) across the doc; here it’s β€œ[!Note]”.


321-322: Standardize callout casing

Same casing issue here (β€œ[!Note]” β†’ β€œ[!NOTE]”).

πŸ“œ Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 48443fd and 6fb3e8f.

πŸ“’ Files selected for processing (1)
  • README.md (8 hunks)
🧰 Additional context used
πŸͺ› markdownlint-cli2 (0.18.1)
README.md

268-268: Emphasis style
Expected: underscore; Actual: asterisk

(MD049, emphasis-style)


268-268: Emphasis style
Expected: underscore; Actual: asterisk

(MD049, emphasis-style)

πŸ”‡ Additional comments (6)
README.md (6)

29-30: Readable section break β€” LGTM

Nice structural divider; improves scanability.


58-59: Readable section break β€” LGTM

Consistent with earlier divider.


82-83: Readable section break β€” LGTM

Good for separating install from config.


195-197: Helpful calibration fallback note β€” LGTM

Clear guidance with a direct link; no changes needed.


208-209: Readable section break β€” LGTM

Keeps Configure distinct from prior content.


302-303: Readable section break β€” LGTM

Good separation before Terminology.

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

πŸ“œ Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 5dafc2f and 03dcdae.

πŸ“’ Files selected for processing (1)
  • README.md (9 hunks)
🧰 Additional context used
πŸͺ› markdownlint-cli2 (0.18.1)
README.md

269-269: Emphasis style
Expected: underscore; Actual: asterisk

(MD049, emphasis-style)


269-269: Emphasis style
Expected: underscore; Actual: asterisk

(MD049, emphasis-style)

⏰ 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: build (3.11)
πŸ”‡ Additional comments (4)
README.md (4)

12-14: Verify the "Buy Me A Coffee" button HTML renders correctly in GitHub and Home Assistant docs.

The HTML markup for the button appears valid, but confirm the image loads and the link functions properly in both contexts where this README may be viewed.


30-30: Horizontal rule separators improve document structure.

Adding separator lines (---) throughout the document helps with readability and clearly delineates major sections. This is a solid documentation improvement that aligns well with the expanded feature set (Adaptive Controller, new services).

Also applies to: 59-59, 83-83, 209-209, 303-303


196-197: Calibration troubleshooting note with discussion link is a helpful addition.

Linking to discussion #36 provides users with practical guidance when calibration fails, improving the onboarding experience.


245-245: Adaptive Controller documentation clearly positioned among existing options.

The new Adaptive Controller option is well-placed and the clarifying note (line 247-248) that SAT auto-tunes gains when it's active is accurate and helpful. This aligns with the broader PR changes introducing adaptive tuning capabilities.

Also applies to: 247-248

The heating curve coefficient is a configurable parameter in SAT that allows you to adjust the relationship between the outdoor temperature and the heating system output. This is useful for optimizing the heating system's performance in different weather conditions, as it allows you to adjust how much heat the system delivers as the outdoor temperature changes. By tweaking this parameter, you can achieve a more efficient and comfortable heating system.

*Automatic Gains Value*: Automatically tweaking the aggressiveness of the Kp, Ki and Kd gains.
*Automatic Gains Value*: Automatically tweaking the aggressiveness of the Kp, Ki and Kd gains when Classic or Improved Controller is in use.
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟑 Minor

Fix emphasis style inconsistency flagged by linter.

Line 269 uses asterisks for emphasis (*Automatic Gains Value*) but markdownlint expects underscores (_Automatic Gains Value_) per the repo's Markdown style rules.

Apply this diff to fix the emphasis style:

-*Automatic Gains Value*: Automatically tweaking the aggressiveness of the Kp, Ki and Kd gains when Classic or Improved Controller is in use.
+_Automatic Gains Value_: Automatically tweaking the aggressiveness of the Kp, Ki and Kd gains when Classic or Improved Controller is in use.

Note: The text clarification ("when Classic or Improved Controller is in use") is appropriate given the new Adaptive Controller option introduced earlier in the document.

πŸ“ Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
*Automatic Gains Value*: Automatically tweaking the aggressiveness of the Kp, Ki and Kd gains when Classic or Improved Controller is in use.
_Automatic Gains Value_: Automatically tweaking the aggressiveness of the Kp, Ki and Kd gains when Classic or Improved Controller is in use.
🧰 Tools
πŸͺ› markdownlint-cli2 (0.18.1)

269-269: Emphasis style
Expected: underscore; Actual: asterisk

(MD049, emphasis-style)


269-269: Emphasis style
Expected: underscore; Actual: asterisk

(MD049, emphasis-style)

πŸ€– Prompt for AI Agents
In README.md around line 269, the emphasis uses asterisks (*Automatic Gains
Value*) which violates the repo's markdownlint rule; replace the asterisks with
underscores so it reads _Automatic Gains Value_, leaving the rest of the
sentence unchanged (retain "when Classic or Improved Controller is in use");
update that single line to use underscore emphasis to satisfy the linter.

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.

5 participants