core
core copied to clipboard
Add Overkiz DomesticHotWaterProduction
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!)
- [X] 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.
- This PR fixes or closes issue: fixes #
- This PR is related to issue:
- Link to documentation pull request:
Checklist
- [ ] The code change is tested and works locally.
- [X] Local tests pass. Your PR cannot be merged unless tests pass
- [X] There is no commented out code in this PR.
- [X] I have followed the development checklist
- [X] 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:
- [ ] Documentation added/updated for www.home-assistant.io
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 runningpython3 -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:
- [ ] I have reviewed two other open pull requests in this repository.
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 closeCloses the issue.@home-assistant rename Awesome new titleChange the title of the issue.@home-assistant reopenReopen the issue.@home-assistant unassign overkizRemoves the current integration label and assignees on the issue, add the integration domain after the command.
@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.
@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.
@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 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 :
- io:AtlanticDomesticHotWaterProductionV2_CETHI_V4_IOComponent
- io:AtlanticDomesticHotWaterProductionV2_CE_FLAT_C2_IOComponent
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...
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
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.
@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
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
@nyroDev I found another user in case you need more testers. https://github.com/home-assistant/core/issues/82148
@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...
@jncanches and @MassimoL06 it could be great if you could test it, this PR should fix your overkiz integration with your respective water heater.