173 lines
5.5 KiB
Python
173 lines
5.5 KiB
Python
"""Support for Rheem EcoNet water heaters."""
|
|
import logging
|
|
|
|
from pyeconet.equipment import EquipmentType
|
|
from pyeconet.equipment.water_heater import WaterHeaterOperationMode
|
|
|
|
from homeassistant.components.water_heater import (
|
|
STATE_ECO,
|
|
STATE_ELECTRIC,
|
|
STATE_GAS,
|
|
STATE_HEAT_PUMP,
|
|
STATE_HIGH_DEMAND,
|
|
STATE_PERFORMANCE,
|
|
WaterHeaterEntity,
|
|
WaterHeaterEntityFeature,
|
|
)
|
|
from homeassistant.config_entries import ConfigEntry
|
|
from homeassistant.const import ATTR_TEMPERATURE, STATE_OFF
|
|
from homeassistant.core import HomeAssistant, callback
|
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
|
|
|
from . import EcoNetEntity
|
|
from .const import DOMAIN, EQUIPMENT
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
ECONET_STATE_TO_HA = {
|
|
WaterHeaterOperationMode.ENERGY_SAVING: STATE_ECO,
|
|
WaterHeaterOperationMode.HIGH_DEMAND: STATE_HIGH_DEMAND,
|
|
WaterHeaterOperationMode.OFF: STATE_OFF,
|
|
WaterHeaterOperationMode.HEAT_PUMP_ONLY: STATE_HEAT_PUMP,
|
|
WaterHeaterOperationMode.ELECTRIC_MODE: STATE_ELECTRIC,
|
|
WaterHeaterOperationMode.GAS: STATE_GAS,
|
|
WaterHeaterOperationMode.PERFORMANCE: STATE_PERFORMANCE,
|
|
}
|
|
HA_STATE_TO_ECONET = {value: key for key, value in ECONET_STATE_TO_HA.items()}
|
|
|
|
SUPPORT_FLAGS_HEATER = (
|
|
WaterHeaterEntityFeature.TARGET_TEMPERATURE
|
|
| WaterHeaterEntityFeature.OPERATION_MODE
|
|
)
|
|
|
|
|
|
async def async_setup_entry(
|
|
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
|
|
) -> None:
|
|
"""Set up EcoNet water heater based on a config entry."""
|
|
equipment = hass.data[DOMAIN][EQUIPMENT][entry.entry_id]
|
|
async_add_entities(
|
|
[
|
|
EcoNetWaterHeater(water_heater)
|
|
for water_heater in equipment[EquipmentType.WATER_HEATER]
|
|
],
|
|
)
|
|
|
|
|
|
class EcoNetWaterHeater(EcoNetEntity, WaterHeaterEntity):
|
|
"""Define a Econet water heater."""
|
|
|
|
def __init__(self, water_heater):
|
|
"""Initialize."""
|
|
super().__init__(water_heater)
|
|
self._running = water_heater.running
|
|
self._poll = True
|
|
self.water_heater = water_heater
|
|
self.econet_state_to_ha = {}
|
|
self.ha_state_to_econet = {}
|
|
|
|
@callback
|
|
def on_update_received(self):
|
|
"""Update was pushed from the ecoent API."""
|
|
if self._running != self.water_heater.running:
|
|
# Water heater running state has changed so check usage on next update
|
|
self._poll = True
|
|
self._running = self.water_heater.running
|
|
self.async_write_ha_state()
|
|
|
|
@property
|
|
def is_away_mode_on(self):
|
|
"""Return true if away mode is on."""
|
|
return self._econet.away
|
|
|
|
@property
|
|
def current_operation(self):
|
|
"""Return current operation."""
|
|
econet_mode = self.water_heater.mode
|
|
_current_op = STATE_OFF
|
|
if econet_mode is not None:
|
|
_current_op = ECONET_STATE_TO_HA[econet_mode]
|
|
|
|
return _current_op
|
|
|
|
@property
|
|
def operation_list(self):
|
|
"""List of available operation modes."""
|
|
econet_modes = self.water_heater.modes
|
|
op_list = []
|
|
for mode in econet_modes:
|
|
if (
|
|
mode is not WaterHeaterOperationMode.UNKNOWN
|
|
and mode is not WaterHeaterOperationMode.VACATION
|
|
):
|
|
ha_mode = ECONET_STATE_TO_HA[mode]
|
|
op_list.append(ha_mode)
|
|
return op_list
|
|
|
|
@property
|
|
def supported_features(self):
|
|
"""Return the list of supported features."""
|
|
if self.water_heater.modes:
|
|
if self.water_heater.supports_away:
|
|
return SUPPORT_FLAGS_HEATER | WaterHeaterEntityFeature.AWAY_MODE
|
|
return SUPPORT_FLAGS_HEATER
|
|
if self.water_heater.supports_away:
|
|
return (
|
|
WaterHeaterEntityFeature.TARGET_TEMPERATURE
|
|
| WaterHeaterEntityFeature.AWAY_MODE
|
|
)
|
|
return WaterHeaterEntityFeature.TARGET_TEMPERATURE
|
|
|
|
def set_temperature(self, **kwargs):
|
|
"""Set new target temperature."""
|
|
if (target_temp := kwargs.get(ATTR_TEMPERATURE)) is not None:
|
|
self.water_heater.set_set_point(target_temp)
|
|
else:
|
|
_LOGGER.error("A target temperature must be provided")
|
|
|
|
def set_operation_mode(self, operation_mode):
|
|
"""Set operation mode."""
|
|
op_mode_to_set = HA_STATE_TO_ECONET.get(operation_mode)
|
|
if op_mode_to_set is not None:
|
|
self.water_heater.set_mode(op_mode_to_set)
|
|
else:
|
|
_LOGGER.error("Invalid operation mode: %s", operation_mode)
|
|
|
|
@property
|
|
def target_temperature(self):
|
|
"""Return the temperature we try to reach."""
|
|
return self.water_heater.set_point
|
|
|
|
@property
|
|
def min_temp(self):
|
|
"""Return the minimum temperature."""
|
|
return self.water_heater.set_point_limits[0]
|
|
|
|
@property
|
|
def max_temp(self):
|
|
"""Return the maximum temperature."""
|
|
return self.water_heater.set_point_limits[1]
|
|
|
|
@property
|
|
def should_poll(self) -> bool:
|
|
"""Return True if entity has to be polled for state.
|
|
|
|
False if entity pushes its state to HA.
|
|
"""
|
|
return self._poll
|
|
|
|
async def async_update(self):
|
|
"""Get the latest energy usage."""
|
|
await self.water_heater.get_energy_usage()
|
|
await self.water_heater.get_water_usage()
|
|
self.async_write_ha_state()
|
|
self._poll = False
|
|
|
|
def turn_away_mode_on(self):
|
|
"""Turn away mode on."""
|
|
self.water_heater.set_away_mode(True)
|
|
|
|
def turn_away_mode_off(self):
|
|
"""Turn away mode off."""
|
|
self.water_heater.set_away_mode(False)
|