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 device AtlanticPassAPCHeatingZone #785

Closed
2 changes: 2 additions & 0 deletions custom_components/tahoma/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from .climate_devices.atlantic_pass_apc_heating_and_cooling_zone import (
AtlanticPassAPCHeatingAndCoolingZone,
)
from .climate_devices.atlantic_pass_apc_heating_zone import AtlanticPassAPCHeatingZone
from .climate_devices.atlantic_pass_apc_zone_control import AtlanticPassAPCZoneControl
from .climate_devices.atlantic_pass_apcdhw import AtlanticPassAPCDHW
from .climate_devices.dimmer_exterior_heating import DimmerExteriorHeating
Expand All @@ -37,6 +38,7 @@
UIWidget.ATLANTIC_ELECTRICAL_HEATER_WITH_ADJUSTABLE_TEMPERATURE_SETPOINT: AtlanticElectricalHeaterWithAdjustableTemperatureSetpoint,
UIWidget.ATLANTIC_ELECTRICAL_TOWEL_DRYER: AtlanticElectricalTowelDryer,
UIWidget.ATLANTIC_PASS_APC_DHW: AtlanticPassAPCDHW,
UIWidget.ATLANTIC_PASS_APC_HEATING_ZONE: AtlanticPassAPCHeatingZone,
UIWidget.ATLANTIC_PASS_APC_HEATING_AND_COOLING_ZONE: AtlanticPassAPCHeatingAndCoolingZone,
UIWidget.ATLANTIC_PASS_APC_ZONE_CONTROL: AtlanticPassAPCZoneControl,
UIWidget.DIMMER_EXTERIOR_HEATING: DimmerExteriorHeating,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,260 @@
"""Support for Atlantic Pass APC Heating Zone."""
import logging
from typing import List, Optional

from pyoverkiz.enums import OverkizState

from homeassistant.components.climate import (
SUPPORT_PRESET_MODE,
SUPPORT_TARGET_TEMPERATURE,
ClimateEntity,
)
from homeassistant.components.climate.const import (
HVAC_MODE_AUTO,
HVAC_MODE_HEAT,
HVAC_MODE_OFF,
PRESET_AWAY,
PRESET_COMFORT,
PRESET_ECO,
)
from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS

from ..coordinator import OverkizDataUpdateCoordinator
from ..entity import OverkizEntity

_LOGGER = logging.getLogger(__name__)

CUSTOM_PRESET_DEROGATION = "Derogation"
CUSTOM_PRESET_AUTO = "Auto"
CUSTOM_PRESET_STOP = "Stop"

COMMAND_REFRESH_COMFORT_HEATING_TARGET_TEMPERATURE = (
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you please add all these states and commands to https://github.com/iMicknl/python-overkiz-api/tree/main/pyoverkiz/enums ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Should i also add commands / states not used in this class ?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Only add the ones you need

"refreshComfortHeatingTargetTemperature"
)
COMMAND_REFRESH_DEROGATION_REMAINING_TIME = "refreshDerogationRemainingTime"
COMMAND_REFRESH_ECO_HEATING_TARGET_TEMPERATURE = "refreshEcoHeatingTargetTemperature"
COMMAND_REFRESH_PASS_APC_HEATING_MODE = "refreshPassAPCHeatingMode"
COMMAND_REFRESH_PASS_APC_HEATING_PROFILE = "refreshPassAPCHeatingProfile"
COMMAND_REFRESH_TARGET_TEMPERATURE = "refreshTargetTemperature"
COMMAND_SET_COMFORT_HEATING_TARGET_TEMPERATURE = "setComfortHeatingTargetTemperature"
COMMAND_SET_DEROGATION_ON_OFF_STATE = "setDerogationOnOffState"
COMMAND_SET_DEROGATED_TARGET_TEMPERATURE = "setDerogatedTargetTemperature"
COMMAND_SET_DEROGATION_TIME = "setDerogationTime"
COMMAND_SET_ECO_HEATING_TARGET_TEMPERATURE = "setEcoHeatingTargetTemperature"
COMMAND_SET_OPERATING_MODE = "setOperatingMode"
COMMAND_SET_PASS_APC_HEATING_MODE = "setPassAPCHeatingMode"
COMMAND_SET_TARGET_TEMPERATURE = "setTargetTemperature"

CORE_COMFORT_HEATING_TARGET_TEMPERATURE_STATE = (
"core:ComfortHeatingTargetTemperatureState"
)
CORE_DEROGATED_TARGET_TEMPERATURE_STATE = "core:DerogatedTargetTemperatureState"
CORE_DEROGATION_ON_OFF_STATE = "core:DerogationOnOffState"
CORE_ECO_HEATING_TARGET_TEMPERATURE_STATE = "core:EcoHeatingTargetTemperatureState"
CORE_HEATING_ON_OFF_STATE = "core:HeatingOnOffState"
CORE_TARGET_TEMPERATURE_STATE = "core:TargetTemperatureState"

IO_DEROGATION_REMAINING_TIME_STATE = "io:DerogationRemainingTimeState"
IO_PASS_APC_HEATING_MODE_STATE = "io:PassAPCHeatingModeState"
IO_PASS_APC_HEATING_PROFILE_STATE = "io:PassAPCHeatingProfileState"
IO_TARGET_HEATING_LEVEL_STATE = "io:TargetHeatingLevelState"

PASS_APC_HEATING_MODE_STATE_ABSENCE = "absence"
PASS_APC_HEATING_MODE_STATE_COMFORT = "comfort"
PASS_APC_HEATING_MODE_STATE_DEROGATION = "derogation"
PASS_APC_HEATING_MODE_STATE_INTERNAL_SCHEDULING = "internalScheduling"
PASS_APC_HEATING_MODE_STATE_STOP = "stop"
PASS_APC_HEATING_PROFILE_STATE_ABSENCE = "absence"
PASS_APC_HEATING_PROFILE_STATE_COMFORT = "comfort"
PASS_APC_HEATING_PROFILE_STATE_DEROGATION = "derogation"
PASS_APC_HEATING_PROFILE_STATE_ECO = "eco"
PASS_APC_HEATING_PROFILE_STATE_INTERNAL_SCHEDULING = "internalScheduling"
PASS_APC_HEATING_PROFILE_STATE_STOP = "stop"

MAP_PRESET_MODES = {
PASS_APC_HEATING_PROFILE_STATE_ECO: PRESET_ECO,
PASS_APC_HEATING_PROFILE_STATE_COMFORT: PRESET_COMFORT,
PASS_APC_HEATING_PROFILE_STATE_INTERNAL_SCHEDULING: CUSTOM_PRESET_AUTO,
PASS_APC_HEATING_PROFILE_STATE_DEROGATION: CUSTOM_PRESET_DEROGATION,
PASS_APC_HEATING_PROFILE_STATE_STOP: CUSTOM_PRESET_STOP,
PASS_APC_HEATING_PROFILE_STATE_ABSENCE: PRESET_AWAY,
}
MAP_REVERSE_PRESET_MODES = {v: k for k, v in MAP_PRESET_MODES.items()}


class AtlanticPassAPCHeatingZone(OverkizEntity, ClimateEntity):
"""Representation of Atlantic Pass APC Heating and Cooling Zone."""

_attr_hvac_modes = [HVAC_MODE_OFF, HVAC_MODE_HEAT, HVAC_MODE_AUTO]
_attr_max_temp = 30
_attr_min_temp = 5
Comment on lines +89 to +90
Copy link
Collaborator

Choose a reason for hiding this comment

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

These values are not exposed by Atlantic?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

not in this device (device number 7)

the navilink sensor (device number 8) have 2 attributes (from 5 to 30) :

2022-02-20 21:24:28 DEBUG (MainThread) [custom_components.tahoma] Unsupported device detected (Device(attributes=States(_states=[.... State(name='core:MaxSensedValue', type=<DataType.FLOAT: 2>, value=30.0), State(name='core:MinSensedValue', type=<DataType.FLOAT: 2>, value=5.0)]),available=True, enabled=True, label=** *(**#**)*, device_url=io://****-****-0589/12309249#8, controllable_name='io:AtlanticPassAPCZoneTemperatureSensor' ....

tahomalink allows to set a temperature between 7 and 35 ...

Copy link
Collaborator

Choose a reason for hiding this comment

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

🤡 And what happens if you set 35? It's applied?
If the values are returned as you Show me, you can retrieve them into the init method using the linked device.

_attr_supported_features = SUPPORT_PRESET_MODE | SUPPORT_TARGET_TEMPERATURE
_attr_temperature_unit = TEMP_CELSIUS

def __init__(self, device_url: str, coordinator: OverkizDataUpdateCoordinator):
"""Init method."""
super().__init__(device_url, coordinator)
self.temperature_device = self.executor.linked_device(8)

@property
def preset_modes(self) -> Optional[List[str]]:
"""Return preset mode list."""

if (
self.executor.select_state(IO_PASS_APC_HEATING_PROFILE_STATE)
== PASS_APC_HEATING_PROFILE_STATE_DEROGATION
):
return [
PRESET_COMFORT,
PRESET_ECO,
CUSTOM_PRESET_AUTO,
CUSTOM_PRESET_DEROGATION,
CUSTOM_PRESET_STOP,
PRESET_AWAY,
]

return [
PRESET_COMFORT,
PRESET_ECO,
CUSTOM_PRESET_AUTO,
CUSTOM_PRESET_STOP,
PRESET_AWAY,
]
jgarec marked this conversation as resolved.
Show resolved Hide resolved

@property
def preset_mode(self) -> Optional[str]:
"""Return the current preset mode, e.g., home, away, temp."""

if (
self.executor.select_state(IO_PASS_APC_HEATING_MODE_STATE)
== PASS_APC_HEATING_MODE_STATE_ABSENCE
):
return PRESET_AWAY

if (
self.executor.select_state(IO_PASS_APC_HEATING_PROFILE_STATE)
== PASS_APC_HEATING_PROFILE_STATE_DEROGATION
):
return CUSTOM_PRESET_DEROGATION

if (
self.executor.select_state(IO_PASS_APC_HEATING_MODE_STATE)
== PASS_APC_HEATING_MODE_STATE_INTERNAL_SCHEDULING
):
return MAP_PRESET_MODES[
self.executor.select_state(IO_PASS_APC_HEATING_PROFILE_STATE)
]

return MAP_PRESET_MODES[
self.executor.select_state(IO_PASS_APC_HEATING_MODE_STATE)
]

async def async_set_preset_mode(self, preset_mode: str) -> None:
"""Set new preset mode."""

if self.preset_mode == CUSTOM_PRESET_DEROGATION:
# revert derogation
await self.executor.async_execute_command(
COMMAND_SET_DEROGATION_ON_OFF_STATE, "off"
)
await self.executor.async_execute_command(
COMMAND_SET_PASS_APC_HEATING_MODE, MAP_REVERSE_PRESET_MODES[preset_mode]
)
await self.refresh_values()

@property
def current_temperature(self) -> Optional[float]:
"""Return the current temperature."""
return float(
self.temperature_device.states.get(OverkizState.CORE_TEMPERATURE).value
)

@property
def hvac_mode(self) -> str:
"""Return hvac operation."""

if (
self.executor.select_state(IO_PASS_APC_HEATING_MODE_STATE)
== PASS_APC_HEATING_MODE_STATE_STOP
):
return HVAC_MODE_OFF

if self.executor.select_state(IO_PASS_APC_HEATING_MODE_STATE) in [
PASS_APC_HEATING_MODE_STATE_INTERNAL_SCHEDULING,
PASS_APC_HEATING_MODE_STATE_ABSENCE,
]:
return HVAC_MODE_AUTO

return HVAC_MODE_HEAT
jgarec marked this conversation as resolved.
Show resolved Hide resolved

async def async_set_hvac_mode(self, hvac_mode: str) -> None:
"""Set new target hvac mode."""

if hvac_mode == HVAC_MODE_OFF:
await self.executor.async_execute_command(
COMMAND_SET_PASS_APC_HEATING_MODE, PASS_APC_HEATING_MODE_STATE_STOP
)
else:
if self.hvac_mode == HVAC_MODE_OFF:
tetienne marked this conversation as resolved.
Show resolved Hide resolved
await self.executor.async_execute_command(
COMMAND_SET_PASS_APC_HEATING_MODE, "on"
)
if hvac_mode == HVAC_MODE_AUTO:
await self.executor.async_execute_command(
COMMAND_SET_PASS_APC_HEATING_MODE,
PASS_APC_HEATING_MODE_STATE_INTERNAL_SCHEDULING,
)
elif hvac_mode == HVAC_MODE_HEAT:
await self.executor.async_execute_command(
COMMAND_SET_PASS_APC_HEATING_MODE,
PASS_APC_HEATING_MODE_STATE_COMFORT,
)
self.refresh_values()

@property
def target_temperature(self) -> None:
"""Return the temperature."""

if self.preset_mode == PRESET_COMFORT:
return self.executor.select_state(
CORE_COMFORT_HEATING_TARGET_TEMPERATURE_STATE
)
if self.preset_mode == PRESET_ECO:
return self.executor.select_state(CORE_ECO_HEATING_TARGET_TEMPERATURE_STATE)
if self.preset_mode == CUSTOM_PRESET_DEROGATION:
return self.executor.select_state(CORE_DEROGATED_TARGET_TEMPERATURE_STATE)

return self.executor.select_state(CORE_TARGET_TEMPERATURE_STATE)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Here also you can ease the code with a dict.


async def async_set_temperature(self, **kwargs) -> None:
"""Set new temperature."""
temperature = kwargs.get(ATTR_TEMPERATURE)
jgarec marked this conversation as resolved.
Show resolved Hide resolved
jgarec marked this conversation as resolved.
Show resolved Hide resolved

if self.hvac_mode == HVAC_MODE_AUTO:
await self.executor.async_execute_command(
COMMAND_SET_DEROGATION_ON_OFF_STATE, "on"
)
Comment on lines +223 to +225
Copy link
Owner

@iMicknl iMicknl Mar 3, 2022

Choose a reason for hiding this comment

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

Suggested change
await self.executor.async_execute_command(
COMMAND_SET_DEROGATION_ON_OFF_STATE, "on"
)
await self.executor.async_execute_command(
OverkizCommand.SET_DEROGATION_ON_OFF_STATE, OverkizCommandParam.ON
)

Would be great if you could use our enums here (and in all other executions). See https://github.com/home-assistant/core/blob/dev/homeassistant/components/overkiz/climate_entities/atlantic_electrical_heater.py.

However, many of these enums are probably missing and we need to add them to PyOverkiz.

await self.executor.async_execute_command(COMMAND_SET_DEROGATION_TIME, 24)
await self.executor.async_execute_command(
COMMAND_SET_DEROGATED_TARGET_TEMPERATURE, temperature
)
else:
if self.preset_mode == "comfort":
jgarec marked this conversation as resolved.
Show resolved Hide resolved
await self.executor.async_execute_command(
COMMAND_SET_COMFORT_HEATING_TARGET_TEMPERATURE, temperature
)
elif self.preset_mode == "eco":
await self.executor.async_execute_command(
COMMAND_SET_ECO_HEATING_TARGET_TEMPERATURE, temperature
)

await self.refresh_values()

async def refresh_values(self) -> None:
"""Refresh some values not always updated."""

await self.executor.async_execute_command(
COMMAND_REFRESH_PASS_APC_HEATING_PROFILE
)
await self.executor.async_execute_command(COMMAND_REFRESH_PASS_APC_HEATING_MODE)
await self.executor.async_execute_command(COMMAND_REFRESH_TARGET_TEMPERATURE)
1 change: 1 addition & 0 deletions custom_components/tahoma/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
UIWidget.ATLANTIC_ELECTRICAL_HEATER_WITH_ADJUSTABLE_TEMPERATURE_SETPOINT: Platform.CLIMATE, # widgetName, uiClass is HeatingSystem (not supported)
UIWidget.ATLANTIC_ELECTRICAL_TOWEL_DRYER: Platform.CLIMATE, # widgetName, uiClass is HeatingSystem (not supported)
UIWidget.ATLANTIC_PASS_APC_DHW: Platform.CLIMATE, # widgetName, uiClass is WaterHeatingSystem (not supported)
UIWidget.ATLANTIC_PASS_APC_HEATING_ZONE: Platform.CLIMATE, # widgetName, uiClass is HeatingSystem (not supported)
UIWidget.ATLANTIC_PASS_APC_HEATING_AND_COOLING_ZONE: Platform.CLIMATE, # widgetName, uiClass is HeatingSystem (not supported)
UIWidget.ATLANTIC_PASS_APC_ZONE_CONTROL: Platform.CLIMATE, # widgetName, uiClass is HeatingSystem (not supported)
UIWidget.DIMMER_EXTERIOR_HEATING: Platform.CLIMATE, # widgetName, uiClass is ExteriorHeatingSystem (not supported)
Expand Down