Skip to content
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

Add Overkiz DomesticHotWaterProduction #81538

Merged

Conversation

nyroDev
Copy link
Contributor

@nyroDev nyroDev commented Nov 4, 2022

Breaking change

Proposed change

Implement Overkiz DomesticHotWaterProduction, a Water Heater entity generic.

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

This is a port from Ha-Tahoma entity
Please note that I cannot test it myself.

Checklist

  • 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
  • The code has been formatted using Black (black --fast homeassistant tests)
  • Tests have been added to verify that the new code works.

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 link to the changelog, or at minimum a diff between library versions is added to the PR description.
  • Untested files have been added to .coveragerc.

To help with the load of incoming pull requests:

@home-assistant
Copy link

home-assistant bot commented Nov 4, 2022

Hey there @iMicknl, @vlebourl, @tetienne, mind taking a look at this pull request as it has been labeled with an integration (overkiz) you are listed as a code owner for? Thanks!

Code owner commands

Code owners of overkiz can trigger bot actions by commenting:

  • @home-assistant close Closes the issue.
  • @home-assistant rename Awesome new title Change the title of the issue.
  • @home-assistant reopen Reopen the issue.
  • @home-assistant unassign overkiz Removes the current integration label and assignees on the issue, add the integration domain after the command.

@nyroDev
Copy link
Contributor Author

nyroDev commented Nov 4, 2022

@tetienne @iMicknl Update I did from HA-Tahoma:

Add checks for dict return when using .get on select_state

Uses only Water_Entity STATES enabled by HA instead of using custom ones.
-> Not 100% sure about the new mapping I did there.

Add all missings casts and stuff like that to make it works with lint and mypy.

@nyroDev
Copy link
Contributor Author

nyroDev commented Nov 4, 2022

@tetienne @iMicknl After found this code on Jeedom,
And after this comment

I decided to update how the Domestic Water Heater works to handle more controllable name (the case mentionned by @jncanches was not present)

When controllable name was not know, I use a fallback to the "standard" name.

This code could not be tested by me and I'm not sure if we could find a tester for each controllable name...

let me know what you think about that.

@tetienne
Copy link
Contributor

tetienne commented Nov 5, 2022

@nyroDev When @iMicknl, @vlebourl and myself rework the legacy tahoma integrations, it was decided to use the widget ui or the ui class which are more generic as they can be common to multiple devices and so ease the maintenance. Previous integration was full of if condition, that you can ease using a dict, but that’s still hard to maintain when new hardware are released.
Here, can you check if all these devices have a common property (widget, class, profile, etc)?

@nyroDev
Copy link
Contributor Author

nyroDev commented Nov 6, 2022

@nyroDev When @iMicknl, @vlebourl and myself rework the legacy tahoma integrations, it was decided to use the widget ui or the ui class which are more generic as they can be common to multiple devices and so ease the maintenance. Previous integration was full of if condition, that you can ease using a dict, but that’s still hard to maintain when new hardware are released. Here, can you check if all these devices have a common property (widget, class, profile, etc)?

@tetienne According to the previous code, ui Class WaterHeatingSystem and widget DomesticHotWaterProduction could be attached to many different devices.

The only setup exemple I could find in pyoverkiz are :

Both have the same uiclass and widget.

The only name difference is the controllableName

So we can't do what you're suggesting.

What I tried to do in this PR is slighlty better than what was done before:
List only 1 time all ctrollable_name in a dict and map them to custom name to apply same action on differerent controllable name.

What may be done is do this detection regarding available command and/or states.
The problem with this approach will be :
Which command should we use when we face multiples commands do the same?

As an exemple:
io:AtlanticDomesticHotWaterProductionV2_CE_FLAT_C2_IOComponent supports these states:

  • core:BoostModeDurationState
  • core:BoostEndDateState
  • core:BoostStartDateState
  • io:DHWBoostModeState
  • core:OperatingModeState with a possible boost value

io:AtlanticDomesticHotWaterProductionV2_CETHI_V4_IOComponent supports these states:

  • core:BoostModeDurationState
  • core:OperatingModeState with a possible boost value

How should we detect if the water entity is in boost mode?
Previous code uses io:DHWBoostModeState for flat device, core:OperatingModeState > 0 for CETHI

I implied that if the code was done that way, there was a reason.
So I replicated this here.

The main problem is that we don't have all controllable_name and exemple setup available.

I think this kind of information could may be found in the cozytouch app, but I don't have any of these devices nor the ability to uncompile apk...

Again, I tried to conserve as much as possible the behavior that was previously in ha-tahoma...

@fbonelle
Copy link

fbonelle commented Nov 6, 2022

Hello,

Since I migrated from tahoma integration to legacy overkiz, my Hot Water Production Device is not well detected (brand: Thermor - model: Aeromax). May be the following log may help the team implement missing cases ? :

`2022-11-06 14:09:24.333 DEBUG (MainThread) [homeassistant.components.overkiz] The following device has been retrieved. Report an issue if not supported correctly (Device(attributes=States(_states=[]), available=True, enabled=True, label=**, device_url=internal://--5801/pod/0, controllable_name='internal:PodMiniComponent', definition=Definition(commands=CommandDefinitions(_commands=[CommandDefinition(command_name='getName', nparams=0), CommandDefinition(command_name='update', nparams=0), CommandDefinition(command_name='setCountryCode', nparams=1), CommandDefinition(command_name='activateCalendar', nparams=0), CommandDefinition(command_name='deactivateCalendar', nparams=0), CommandDefinition(command_name='refreshPodMode', nparams=0), CommandDefinition(command_name='refreshUpdateStatus', nparams=0), CommandDefinition(command_name='setCalendar', nparams=1), CommandDefinition(command_name='setLightingLedPodMode', nparams=1), CommandDefinition(command_name='setPodLedOff', nparams=0), CommandDefinition(command_name='setPodLedOn', nparams=0)]), states=[StateDefinition(qualified_name='core:ConnectivityState', type='DiscreteState', values=['offline', 'online']), StateDefinition(qualified_name='core:CountryCodeState', type='DataState', values=None), StateDefinition(qualified_name='core:LocalIPv4AddressState', type='DataState', values=None), StateDefinition(qualified_name='core:NameState', type='DataState', values=None), StateDefinition(qualified_name='internal:LastActionConfigButtonState', type='DiscreteState', values=['doublePress', 'longPress', 'simplePress', 'triplePress', 'veryLongPress']), StateDefinition(qualified_name='internal:LightingLedPodModeState', type='ContinuousState', values=None)], widget_name='Pod', ui_class='Pod', qualified_name='internal:PodMiniComponent'), data_properties=None, widget=<UIWidget.POD: 'Pod'>, ui_class=<UIClass.POD: 'Pod'>, states=States(_states=[State(name='core:NameState', type=<DataType.STRING: 3>, value='Box'), State(name='internal:LightingLedPodModeState', type=<DataType.FLOAT: 2>, value=1.0), State(name='core:CountryCodeState', type=<DataType.STRING: 3>, value='FR'), State(name='core:LocalIPv4AddressState', type=<DataType.STRING: 3>, value='192.168.100.124')]), type=<ProductType.ACTUATOR: 1>, place_oid='ab94092c-3f1e-461c-9d05-92f787eea625'))

2022-11-06 14:09:24.334 DEBUG (MainThread) [homeassistant.components.overkiz] The following device has been retrieved. Report an issue if not supported correctly (Device(attributes=States(_states=[]), available=True, enabled=True, label=** (**), device_url=io://--5801/14946082, controllable_name='io:StackComponent', definition=Definition(commands=CommandDefinitions(_commands=[CommandDefinition(command_name='advancedSomfyDiscover', nparams=1), CommandDefinition(command_name='discover1WayController', nparams=2), CommandDefinition(command_name='discoverActuators', nparams=1), CommandDefinition(command_name='discoverSensors', nparams=1), CommandDefinition(command_name='discoverSomfyUnsetActuators', nparams=0), CommandDefinition(command_name='joinNetwork', nparams=0), CommandDefinition(command_name='resetNetworkSecurity', nparams=0), CommandDefinition(command_name='shareNetwork', nparams=0)]), states=[], widget_name='IOStack', ui_class='ProtocolGateway', qualified_name='io:StackComponent'), data_properties=None, widget=<UIWidget.IOSTACK: 'IOStack'>, ui_class=<UIClass.PROTOCOL_GATEWAY: 'ProtocolGateway'>, states=States(_states=[]), type=<ProductType.GATEWAY: 5>, place_oid='ab94092c-3f1e-461c-9d05-92f787eea625'))

2022-11-06 14:09:24.334 DEBUG (MainThread) [homeassistant.components.overkiz] The following device has been retrieved. Report an issue if not supported correctly (Device(attributes=States(_states=[State(name='core:Manufacturer', type=<DataType.STRING: 3>, value='Atlantic Group'), State(name='core:FirmwareRevision', type=<DataType.STRING: 3>, value='681008')]), available=True, enabled=True, label=** **, device_url=io://--5801/6489029#1, controllable_name='io:AtlanticDomesticHotWaterProductionIOComponent', definition=Definition(commands=CommandDefinitions(_commands=[CommandDefinition(command_name='advancedRefresh', nparams=1), CommandDefinition(command_name='delayedStopIdentify', nparams=1), CommandDefinition(command_name='getName', nparams=0), CommandDefinition(command_name='identify', nparams=0), CommandDefinition(command_name='refreshManufacturerName', nparams=0), CommandDefinition(command_name='refreshTargetTemperature', nparams=0), CommandDefinition(command_name='refreshWaterConsumption', nparams=0), CommandDefinition(command_name='setComfortTargetTemperature', nparams=1), CommandDefinition(command_name='setEcoTargetTemperature', nparams=1), CommandDefinition(command_name='setFrostProtectionTargetTemperature', nparams=1), CommandDefinition(command_name='setName', nparams=1), CommandDefinition(command_name='setTargetTemperature', nparams=1), CommandDefinition(command_name='startIdentify', nparams=0), CommandDefinition(command_name='stopIdentify', nparams=0), CommandDefinition(command_name='wink', nparams=1), CommandDefinition(command_name='pairOneWayController', nparams=2), CommandDefinition(command_name='refreshAwayModeDuration', nparams=0), CommandDefinition(command_name='refreshBoostModeDuration', nparams=0), CommandDefinition(command_name='refreshCurrentOperatingMode', nparams=0), CommandDefinition(command_name='refreshDHWCapacity', nparams=0), CommandDefinition(command_name='refreshDHWError', nparams=0), CommandDefinition(command_name='refreshDHWMode', nparams=0), CommandDefinition(command_name='refreshOperatingModeCapabilities', nparams=0), CommandDefinition(command_name='refreshOperatingTime', nparams=0), CommandDefinition(command_name='refreshRateManagement', nparams=0), CommandDefinition(command_name='setAwayModeDuration', nparams=1), CommandDefinition(command_name='setBoostModeDuration', nparams=1), CommandDefinition(command_name='setCurrentOperatingMode', nparams=1), CommandDefinition(command_name='setDHWMode', nparams=1), CommandDefinition(command_name='setHaltedTargetTemperature', nparams=1), CommandDefinition(command_name='setRateManagement', nparams=1), CommandDefinition(command_name='unpairAllOneWayControllers', nparams=0), CommandDefinition(command_name='unpairOneWayController', nparams=2)]), states=[StateDefinition(qualified_name='core:BoostModeDurationState', type='ContinuousState', values=None), StateDefinition(qualified_name='core:ComfortTargetTemperatureState', type='ContinuousState', values=None), StateDefinition(qualified_name='core:DiscreteRSSILevelState', type='DiscreteState', values=['good', 'low', 'normal', 'verylow']), StateDefinition(qualified_name='core:EcoTargetTemperatureState', type='ContinuousState', values=None), StateDefinition(qualified_name='core:FrostProtectionTargetTemperatureState', type='ContinuousState', values=None), StateDefinition(qualified_name='core:HaltedTargetTemperatureState', type='ContinuousState', values=None), StateDefinition(qualified_name='core:ManufacturerNameState', type='DataState', values=None), StateDefinition(qualified_name='core:NameState', type='DataState', values=None), StateDefinition(qualified_name='core:OperatingModeState', type='DiscreteState', values=['antifreeze', 'auto', 'away', 'eco', 'frostprotection', 'manual', 'max', 'normal', 'off', 'on', 'prog', 'program', 'boost']), StateDefinition(qualified_name='core:PriorityLockTimerState', type='ContinuousState', values=None), StateDefinition(qualified_name='core:RSSILevelState', type='ContinuousState', values=None), StateDefinition(qualified_name='core:SecuredPositionTemperatureState', type='ContinuousState', values=None), StateDefinition(qualified_name='core:StatusState', type='DiscreteState', values=['available', 'unavailable']), StateDefinition(qualified_name='core:TargetTemperatureState', type='ContinuousState', values=None), StateDefinition(qualified_name='core:TemperatureState', type='ContinuousState', values=None), StateDefinition(qualified_name='core:VersionState', type='ContinuousState', values=None), StateDefinition(qualified_name='core:WaterConsumptionState', type='ContinuousState', values=None), StateDefinition(qualified_name='io:AwayModeDurationState', type='ContinuousState', values=None), StateDefinition(qualified_name='io:DHWCapacityState', type='ContinuousState', values=None), StateDefinition(qualified_name='io:DHWErrorState', type='DataState', values=None), StateDefinition(qualified_name='io:DHWModeState', type='DiscreteState', values=['autoMode', 'manualEcoActive', 'manualEcoInactive']), StateDefinition(qualified_name='io:ElectricBoosterOperatingTimeState', type='ContinuousState', values=None), StateDefinition(qualified_name='io:HeatPumpOperatingTimeState', type='ContinuousState', values=None), StateDefinition(qualified_name='io:OperatingModeCapabilitiesState', type='DataState', values=None), StateDefinition(qualified_name='io:PriorityLockLevelState', type='DiscreteState', values=['comfortLevel1', 'comfortLevel2', 'comfortLevel3', 'comfortLevel4', 'environmentProtection', 'humanProtection', 'userLevel1', 'userLevel2']), StateDefinition(qualified_name='io:PriorityLockOriginatorState', type='DiscreteState', values=['LSC', 'SAAC', 'SFC', 'UPS', 'externalGateway', 'localUser', 'myself', 'rain', 'security', 'temperature', 'timer', 'user', 'wind']), StateDefinition(qualified_name='io:RateManagementState', type='DiscreteState', values=['forbidden', 'no', 'recommended', 'unsuitable', 'wanted'])], widget_name='DomesticHotWaterProduction', ui_class='WaterHeatingSystem', qualified_name='io:AtlanticDomesticHotWaterProductionIOComponent'), data_properties=None, widget=<UIWidget.DOMESTIC_HOT_WATER_PRODUCTION: 'DomesticHotWaterProduction'>, ui_class=<UIClass.WATER_HEATING_SYSTEM: 'WaterHeatingSystem'>, states=States(_states=[State(name='core:NameState', type=<DataType.STRING: 3>, value='DHWP Actuator'), State(name='core:VersionState', type=<DataType.STRING: 3>, value='36383130303820202020'), State(name='core:PriorityLockTimerState', type=<DataType.INTEGER: 1>, value=0), State(name='core:StatusState', type=<DataType.STRING: 3>, value='available'), State(name='core:DiscreteRSSILevelState', type=<DataType.STRING: 3>, value='normal'), State(name='core:RSSILevelState', type=<DataType.FLOAT: 2>, value=74.0), State(name='core:TemperatureState', type=<DataType.FLOAT: 2>, value=51.5), State(name='io:RateManagementState', type=<DataType.STRING: 3>, value='?'), State(name='io:OperatingModeCapabilitiesState', type=<DataType.JSON_OBJECT: 11>, value={'relaunch': 1, 'absence': 1, 'rate_management': 0, 'energy_demand_status': 1}), State(name='core:OperatingModeState', type=<DataType.JSON_OBJECT: 11>, value={'relaunch': 'Keep_Current_Value ', 'absence': 'Keep_Current_Value'}), State(name='core:WaterConsumptionState', type=<DataType.INTEGER: 1>, value=417), State(name='io:DHWErrorState', type=<DataType.JSON_OBJECT: 11>, value={'code': 0, 'family': 'W', 'type': 0}), State(name='io:HeatPumpOperatingTimeState', type=<DataType.INTEGER: 1>, value=8160), State(name='io:ElectricBoosterOperatingTimeState', type=<DataType.INTEGER: 1>, value=295), State(name='io:DHWModeState', type=<DataType.STRING: 3>, value='manualEcoActive'), State(name='core:TargetTemperatureState', type=<DataType.FLOAT: 2>, value=54.0), State(name='core:BoostModeDurationState', type=<DataType.INTEGER: 1>, value=0), State(name='io:AwayModeDurationState', type=<DataType.STRING: 3>, value='0'), State(name='core:ManufacturerNameState', type=<DataType.STRING: 3>, value='Thermor')]), type=<ProductType.ACTUATOR: 1>, place_oid='ab94092c-3f1e-461c-9d05-92f787eea625'))

2022-11-06 14:09:24.336 DEBUG (MainThread) [homeassistant.components.overkiz] The following device has been retrieved. Report an issue if not supported correctly (Device(attributes=States(_states=[State(name='core:Manufacturer', type=<DataType.STRING: 3>, value='Atlantic Group'), State(name='core:FirmwareRevision', type=<DataType.STRING: 3>, value='681008'), State(name='core:PowerSourceType', type=<DataType.STRING: 3>, value='mainSupply'), State(name='core:MeasuredValueType', type=<DataType.STRING: 3>, value='core:ElectricalEnergyInWh')]), available=True, enabled=True, label=** (#), device_url=io://--5801/6489029#2, controllable_name='io:DHWCumulatedElectricalEnergyConsumptionIOSystemDeviceSensor', definition=Definition(commands=CommandDefinitions(_commands=[CommandDefinition(command_name='refreshElectricEnergyConsumption', nparams=0)]), states=[StateDefinition(qualified_name='core:ConsumptionTariff0State', type='ContinuousState', values=None), StateDefinition(qualified_name='core:ConsumptionTariff1State', type='ContinuousState', values=None), StateDefinition(qualified_name='core:ConsumptionTariff2State', type='ContinuousState', values=None), StateDefinition(qualified_name='core:ConsumptionTariff3State', type='ContinuousState', values=None), StateDefinition(qualified_name='core:ConsumptionTariff4State', type='ContinuousState', values=None), StateDefinition(qualified_name='core:ConsumptionTariff5State', type='ContinuousState', values=None), StateDefinition(qualified_name='core:ConsumptionTariff6State', type='ContinuousState', values=None), StateDefinition(qualified_name='core:ConsumptionTariff7State', type='ContinuousState', values=None), StateDefinition(qualified_name='core:ConsumptionTariff8State', type='ContinuousState', values=None), StateDefinition(qualified_name='core:ConsumptionTariff9State', type='ContinuousState', values=None), StateDefinition(qualified_name='core:ElectricEnergyConsumptionState', type='ContinuousState', values=None), StateDefinition(qualified_name='core:StatusState', type='DiscreteState', values=['available', 'unavailable'])], widget_name='CumulativeElectricPowerConsumptionSensor', ui_class='ElectricitySensor', qualified_name='io:DHWCumulatedElectricalEnergyConsumptionIOSystemDeviceSensor'), data_properties=None, widget=<UIWidget.CUMULATIVE_ELECTRIC_POWER_CONSUMPTION_SENSOR: 'CumulativeElectricPowerConsumptionSensor'>, ui_class=<UIClass.ELECTRICITY_SENSOR: 'ElectricitySensor'>, states=States(_states=[State(name='core:StatusState', type=<DataType.STRING: 3>, value='available'), State(name='core:ElectricEnergyConsumptionState', type=<DataType.INTEGER: 1>, value=3968574)]), type=<ProductType.SENSOR: 2>, place_oid='ab94092c-3f1e-461c-9d05-92f787eea625'))`

Regards

@nyroDev
Copy link
Contributor Author

nyroDev commented Nov 6, 2022

Thanks @fbonelle, it does help.
You're device controllable_name is io:AtlanticDomesticHotWaterProductionIOComponent, which I added on this PR
Could you tell me if your device was working correctly with the old integration Ha-Tahoma?
As far as I can tell, the boost mode was not detected correctly

@tetienne I'll rewrite everything to detect existing states/command, it could works better I think.

@fbonelle I'll let you know when you could test this PR.

@tetienne
Copy link
Contributor

tetienne commented Nov 6, 2022

@nyroDev I checked at the code on ha-tahoma, and was not aware we were using the controllable name. Sorry for my previous comment as you just tried to backport our code.

Perhaps have a look to my WIP PR about using CoverEntityDescription. It can give you some ideas to ease your code with ClimateEntityDescription

@fbonelle
Copy link

fbonelle commented Nov 6, 2022

Thanks @fbonelle, it does help. You're device controllable_name is io:AtlanticDomesticHotWaterProductionIOComponent, which I added on this PR Could you tell me if your device was working correctly with the old integration Ha-Tahoma? As far as I can tell, the boost mode was not detected correctly

@tetienne I'll rewrite everything to detect existing states/command, it could works better I think.

@fbonelle I'll let you know when you could test this PR.

Hello,

It was not working at 100%.

Was missing boost mode (and I guess the economic mode). I have just checked what the cozytouch application can do:

  • Automatic mode
  • Economic mode
  • Manual mode
  • Boost (and asking how many days in boost mode)

A really newby question: how do I test the pull request ? ;)

Regards

@iMicknl
Copy link
Contributor

iMicknl commented Nov 16, 2022

@nyroDev I found another user in case you need more testers. #82148

@nyroDev
Copy link
Contributor Author

nyroDev commented Nov 16, 2022

@iMicknl @tetienne I updated the whole code in order to detect which command/states are available.
After reviewing the 3 differents devices setup I got, it should work, at least on paper...
After you checked the code, the next step will be to test it out with real user if possible...

Copy link
Member

@Quentame Quentame left a comment

Choose a reason for hiding this comment

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

Some questions but good overall

@nyroDev
Copy link
Contributor Author

nyroDev commented Nov 20, 2022

@jncanches and @MassimoL06 it could be great if you could test it, this PR should fix your overkiz integration with your respective water heater.

Copy link
Member

@Quentame Quentame left a comment

Choose a reason for hiding this comment

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

LGTM

Discussed with @iMicknl @nyroDev : PR is ready and user feedback will be welcomed.

@Quentame Quentame merged commit 73cd263 into home-assistant:dev Nov 29, 2022
@nyroDev nyroDev deleted the overkiz/domesticHotWaterProduction branch November 29, 2022 23:29
Copy link
Member

@MartinHjelmare MartinHjelmare left a comment

Choose a reason for hiding this comment

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

Please address the comment in a new PR. Thanks!

return

if self._is_boost_mode_on:
# We're setting a non Boost mode and the device is currently in Boost mode, the following code remove all boost operations
Copy link
Member

Choose a reason for hiding this comment

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

Please break long comments around 88 characters per line.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@github-actions github-actions bot locked and limited conversation to collaborators Dec 1, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

overkiz integration not complete for Atlantic Heat water device
6 participants