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

Skip to content

Conversation

@tmenguy
Copy link
Contributor

@tmenguy tmenguy commented Mar 13, 2025

Hi,

Took the good work from @NatMarchand, tweaked it a bit for retro-compatibility to create a new pull request from my repo and using it in conjunction with my Netatmo customer component (that I'll merge in yours), works fine for me.

BR
Thomas

Summary by Sourcery

Introduce Pilot Wire support for climate control, enabling integration with Netatmo devices. Enhance module classes with ApplianceTypeMixin for better device categorization and add tests to verify Pilot Wire functionality.

New Features:

  • Add support for Pilot Wire ("fil pilote") functionality in the climate control system, allowing integration with Netatmo devices.

Enhancements:

  • Refactor the module classes to include ApplianceTypeMixin where applicable, improving the categorization of device types.

Tests:

  • Add a test to verify the functionality of rooms with climate devices supporting Pilot Wire, ensuring correct device type and support flag.

tmenguy and others added 30 commits February 20, 2024 01:03
…, introduces a sum energy and an helper to be used in homeassistant primarily
@tmenguy tmenguy requested review from cgtobi and jabesq as code owners March 13, 2025 12:32
@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Mar 13, 2025

Reviewer's Guide by Sourcery

This pull request introduces support for 'Pilot Wire' (fil pilote) functionality, enhancing the existing climate control system by integrating new modes and mappings for Netatmo devices. It includes updates to the room and module classes, as well as new constants and test cases to ensure compatibility and functionality.

Entity relationship diagram for Pilot Wire modes

erDiagram
    ROOM {
        string therm_setpoint_mode
        string therm_setpoint_fp
    }
    NETAMO_CLIMATE_SETPOINT_MODE_TO_PILOT_WIRE {
        string MANUAL
        string MAX
        string OFF
        string HOME
        string FROSTGUARD
        string SCHEDULE
        string AWAY
    }
    NETAMO_PILOT_WIRE_TO_CLIMATE_SETPOINT_MODE {
        string PILOT_WIRE_COMFORT
        string PILOT_WIRE_AWAY
        string PILOT_WIRE_FROST_GUARD
        string PILOT_WIRE_STAND_BY
        string PILOT_WIRE_COMFORT_1
        string PILOT_WIRE_COMFORT_2
    }
    ROOM ||--o{ NETAMO_CLIMATE_SETPOINT_MODE_TO_PILOT_WIRE : maps
    ROOM ||--o{ NETAMO_PILOT_WIRE_TO_CLIMATE_SETPOINT_MODE : maps
Loading

Updated class diagram for Room and Module classes

classDiagram
    class Room {
        +int|None heating_power_request
        +float|None therm_setpoint_temperature
        +str|None therm_setpoint_mode
        +str|None therm_setpoint_fp
        +bool support_pilot_wire
        +int|None therm_setpoint_start_time
        +int|None therm_setpoint_end_time
        +evaluate_device_type()
        +update(RawData raw_data)
        +async_therm_set(str|None mode, float|None temp, int|None end_time, str|None pilot_wire)
        +_async_therm_set(str|None mode, float|None temp, int|None end_time, str|None pilot_wire)
    }
    class ApplianceTypeMixin {
        +str|None appliance_type
    }
    class NLC {
        <<ApplianceTypeMixin>>
    }
    class NLPO {
        <<ApplianceTypeMixin>>
    }
    class NLPD {
        <<ApplianceTypeMixin>>
    }
    class NLPT {
        <<ApplianceTypeMixin>>
    }
    Room --> ApplianceTypeMixin : uses
    NLC --> ApplianceTypeMixin : extends
    NLPO --> ApplianceTypeMixin : extends
    NLPD --> ApplianceTypeMixin : extends
    NLPT --> ApplianceTypeMixin : extends
Loading

File-Level Changes

Change Details Files
Added support for Pilot Wire modes in the Room class.
  • Introduced new constants for Pilot Wire modes.
  • Added mappings between climate setpoint modes and Pilot Wire modes.
  • Updated the Room class to include support for Pilot Wire functionality.
  • Modified the evaluate_device_type method to detect and set support for Pilot Wire.
  • Updated the async_therm_set and _async_therm_set methods to handle Pilot Wire parameters.
src/pyatmo/room.py
src/pyatmo/const.py
Enhanced module classes to support appliance type detection.
  • Added ApplianceTypeMixin to several Legrand module classes.
  • Updated the appliance_type attribute initialization in the ApplianceTypeMixin class.
src/pyatmo/modules/legrand.py
src/pyatmo/modules/module.py
Added test cases for Pilot Wire support.
  • Created a new test case to verify Pilot Wire support in rooms with climate devices.
tests/test_climate.py
Minor refactoring and updates to existing test fixtures.
  • Removed an unnecessary async update call in the async_home_multi fixture.
tests/conftest.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!
  • Generate a plan of action for an issue: Comment @sourcery-ai plan on
    an issue to generate a plan of action for it.

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey @tmenguy - I've reviewed your changes - here's some feedback:

Overall Comments:

  • Consider adding a brief explanation of the purpose and functionality of the pilot wire feature to the description.
  • It might be helpful to include a more detailed explanation of how the pilot wire feature interacts with the existing climate control modes.
Here's what I looked at during the review
  • 🟡 General issues: 2 issues found
  • 🟢 Security: all looks good
  • 🟢 Testing: all looks good
  • 🟡 Complexity: 1 issue found
  • 🟢 Documentation: all looks good

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines 127 to +129
super().__init__(room)
self.home = home
self.support_pilot_wire = False
Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion: Redundant initialization for support_pilot_wire.

The field support_pilot_wire already has a default value in the dataclass declaration. Unless there is a specific reason to reinitialize it in init, consider removing the duplicate assignment to avoid potential confusion.

Suggested change
super().__init__(room)
self.home = home
self.support_pilot_wire = False
super().__init__(room)
self.home = home

await self._async_therm_set(mode, temp, end_time)
await self._async_therm_set(mode, temp, end_time, pilot_wire)

async def _async_therm_set(
Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion: Complex nested logic in _async_therm_set.

The conditional blocks that determine pilot_wire and adjust mode based on support_pilot_wire and climate_type make the function logic quite dense. Consider refactoring this logic into smaller helper functions or reordering the conditions to improve readability and maintainability.

pilot_wire: str | None = None,
) -> bool:
"""Set room temperature set point (OTM)."""
if pilot_wire is None:
Copy link
Contributor

Choose a reason for hiding this comment

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

issue (complexity): Consider extracting the pilot-wire resolution logic into a helper method.

Consider extracting the pilot-wire resolution logic from _async_therm_set into its own helper method. This reduces the deep nesting in the method while keeping the behavior intact. For example:

def _resolve_mode_and_pilot_wire(
    self,
    mode: str | None,
    pilot_wire: str | None,
) -> tuple[str, str]:
    # Default mode if none provided
    if mode is None:
        mode = FROSTGUARD
    # Resolve pilot_wire if not provided
    if pilot_wire is None:
        pilot_wire = NETAMO_CLIMATE_SETPOINT_MODE_TO_PILOT_WIRE.get(
            mode, PILOT_WIRE_FROST_GUARD
        )
        if self.support_pilot_wire and self.climate_type == DeviceType.NLC:
            mode = NETAMO_PILOT_WIRE_TO_CLIMATE_SETPOINT_MODE.get(pilot_wire, FROSTGUARD)
    # If pilot_wire is provided and mode is unset, default to MANUAL
    if pilot_wire is not None and mode is None:
        mode = MANUAL
    return mode, pilot_wire

Then simplify _async_therm_set as follows:

async def _async_therm_set(
    self,
    mode: str | None = None,
    temp: float | None = None,
    end_time: int | None = None,
    pilot_wire: str | None = None,
) -> bool:
    mode, pilot_wire = self._resolve_mode_and_pilot_wire(mode, pilot_wire)

    json_therm_set: dict[str, Any] = {
        "rooms": [
            {
                "id": self.entity_id,
                "therm_setpoint_mode": mode,
            },
        ],
    }
    if temp:
        json_therm_set["rooms"][0]["therm_setpoint_temperature"] = temp
    if end_time:
        json_therm_set["rooms"][0]["therm_setpoint_end_time"] = end_time
    if self.support_pilot_wire and pilot_wire:
        json_therm_set["rooms"][0]["therm_setpoint_fp"] = pilot_wire

    return await self.home.async_set_state(json_therm_set)

This refactoring separates concerns by handling mode and pilot wire resolution in its own function, reducing the overall nesting and improving readability.

…deas and better appliance type management
@tmenguy tmenguy changed the title Pilot Wire ("fil pilote" support) (from @NatMarchand work + small tweaks) Pilot Wire ("fil pilote" support) (from @NatMarchand work + @sbilque + small tweaks) Mar 13, 2025
@tmenguy
Copy link
Contributor Author

tmenguy commented Mar 13, 2025

Hi:

@sbilque and @NatMarchand : added your contributions in this one .... and on my Netatmo custom module too

@tmenguy
Copy link
Contributor Author

tmenguy commented Mar 27, 2025

@cgtobi little nudge here ...

@jabesq
Copy link
Member

jabesq commented Mar 28, 2025

@tmenguy I'll merge this weekend. I might need to do it manually in order to squash some commits to keep git history clean.
I'll create a new release right after.

@tmenguy
Copy link
Contributor Author

tmenguy commented Mar 28, 2025

great! thx @jabesq

@tmenguy
Copy link
Contributor Author

tmenguy commented Mar 30, 2025

@jabesq of you want I can clean this a bit by just having all my stuffs in a single commit if you want and I open another cleaner PR if it helps

jabesq pushed a commit that referenced this pull request Mar 31, 2025
…+ small tweaks) #518

Introduce Pilot Wire support for climate control, enabling integration with
Netatmo devices. Enhance module classes with ApplianceTypeMixin for better
device categorization and add tests to verify Pilot Wire functionality.

New Features:

 * Add support for Pilot Wire ("fil pilote") functionality in the climate
   control system, allowing integration with Netatmo devices.

Enhancements:

 * Refactor the module classes to include ApplianceTypeMixin where applicable,
   improving the categorization of device types.

Tests:

 * Add a test to verify the functionality of rooms with climate devices
   supporting Pilot Wire, ensuring correct device type and support flag.

Commits:

 * Initial commit for support of all schedule types, and fix for historical energy data ≤tmenguy>
 * Corrected devices to use hstoryMixin to get energy
 * Merged historyMixin and Energy has they are effectively doing the sum, introduces a sum energy and an helper to be used in homeassistant primarily
 * removed the daily update
 * Try to get a proper historical data in case of peak / off_peak energy mode, add some tests
 * Fixed correctly the timing end/start of measures
 * removed specidif energy exception to use th egeneric API error, 0lus some logging
 * async update for all homes
 * added some tests for historical data
 * added a way to get the data sum
 * added throttling exception
 * fix for num calls estimation
 * changed type for energy
 * Added historical retrival for other state, begining only for power (to be used to refine homeassistant energy handling
 * added energy sum
 * adjusting estimation calculus
 * slight refactor for readability
 * Support error for unreachable home and bridges ....it is an error, not a normal call
 * remove global energy sum support, no needed anymore, was adding complexity
 * refactor to use self.homes where it should be
 * setting schedules list back as the global list of schedules, for retro-compatibility
 * fix: Align with pre-commit rules
 * Cleaned supported homes with a way simpler approach, thx @cgtobi
 * Added back a list of available homes to be able to select the one needed or not
 * Set BNAS, BNIL and BNLD base classes explicitly

   Firmware versions for these devices are always reported to be `1`, so the
   `FirmwareMixin` can be omitted.

   Both `BNIL` and `BNLD` do not report power consumption, so the `PowerMixin`
   should be omitted.

   Signed-off-by: Stephan Peijnik-Steinwender <[email protected]>
 * Support NLE "connected ecocometer" that is a bridge
 * Remove schedule code API calls, etc ... to make it compatible with old lib
 * removed home update boolean as output, and raise conditionally a reachability error
 * rieman energy method extraction
 * Support for pilot wire (fil pilot) for NLC radiator.

Signed-off-by: tmenguy <[email protected]>
Signed-off-by: Stephan Peijnik-Steinwender <[email protected]>
Signed-off-by: Tobias Sauerwein <[email protected]>
Signed-off-by: Hugo Dupras <[email protected]>
@jabesq
Copy link
Member

jabesq commented Mar 31, 2025

Closing PR due to manual merge

I finally did it! It wasn't easy, and I had to squash everything, but I believe I had no other solution after a year of work. Merge commit: 11e3a07

As a side note, while reviewing your commits, I noticed that some were signed with your professional email. I then realized we met each other during a job interview in 2020, where we briefly discussed Home Assistant. It's a small world!

@jabesq jabesq closed this Mar 31, 2025
@jabesq jabesq mentioned this pull request Mar 31, 2025
@tmenguy
Copy link
Contributor Author

tmenguy commented Mar 31, 2025

Yes Hugo, haven't seen your name! :) I remember too, small world indeed....

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.

2 participants