From 6c34f76bb7fbb9c9457ca4cd26abc61ac4110dda Mon Sep 17 00:00:00 2001 From: w1ll1am23 Date: Tue, 26 Jan 2021 14:55:50 +0000 Subject: [PATCH 01/12] Added econet thermostat support and use get attr for sensors --- .coveragerc | 1 + homeassistant/components/econet/__init__.py | 2 +- .../components/econet/binary_sensor.py | 63 ++--- homeassistant/components/econet/climate.py | 251 ++++++++++++++++++ homeassistant/components/econet/sensor.py | 102 ++++--- 5 files changed, 335 insertions(+), 84 deletions(-) create mode 100644 homeassistant/components/econet/climate.py diff --git a/.coveragerc b/.coveragerc index da6cfd2a3b93f..5d484fc80b217 100644 --- a/.coveragerc +++ b/.coveragerc @@ -217,6 +217,7 @@ omit = homeassistant/components/ecobee/weather.py homeassistant/components/econet/__init__.py homeassistant/components/econet/binary_sensor.py + homeassistant/components/econet/climate.py homeassistant/components/econet/const.py homeassistant/components/econet/sensor.py homeassistant/components/econet/water_heater.py diff --git a/homeassistant/components/econet/__init__.py b/homeassistant/components/econet/__init__.py index dce4550eb1bc6..fddd238051f9f 100644 --- a/homeassistant/components/econet/__init__.py +++ b/homeassistant/components/econet/__init__.py @@ -24,7 +24,7 @@ _LOGGER = logging.getLogger(__name__) -PLATFORMS = ["binary_sensor", "sensor", "water_heater"] +PLATFORMS = ["climate", "binary_sensor", "sensor", "water_heater"] PUSH_UPDATE = "econet.push_update" INTERVAL = timedelta(minutes=60) diff --git a/homeassistant/components/econet/binary_sensor.py b/homeassistant/components/econet/binary_sensor.py index ec8131c510560..49628c4a4845c 100644 --- a/homeassistant/components/econet/binary_sensor.py +++ b/homeassistant/components/econet/binary_sensor.py @@ -4,40 +4,51 @@ from pyeconet.equipment import EquipmentType from homeassistant.components.binary_sensor import ( + DEVICE_CLASS_LOCK, DEVICE_CLASS_OPENING, DEVICE_CLASS_POWER, + DEVICE_CLASS_SOUND, BinarySensorEntity, ) from . import EcoNetEntity from .const import DOMAIN, EQUIPMENT -_LOGGER = logging.getLogger(__name__) - -SENSOR_NAME_RUNNING = "running" SENSOR_NAME_SHUTOFF_VALVE = "shutoff_valve" -SENSOR_NAME_VACATION = "vacation" +SENSOR_NAME_RUNNING = "running" +SENSOR_NAME_SCREEN_LOCKED = "screen_locked" +SENSOR_NAME_BEEP_ENABLED = "beep_enabled" + +SENSOR_NAMES_TO_ATTRIBUTES = { + SENSOR_NAME_SHUTOFF_VALVE: "shutoff_valve_open", + SENSOR_NAME_RUNNING: "running", + SENSOR_NAME_SCREEN_LOCKED: "screen_locked", + SENSOR_NAME_BEEP_ENABLED: "beep_enabled", +} + +SENSOR_NAMES_TO_DEVICE_CLASS = { + SENSOR_NAME_SHUTOFF_VALVE: DEVICE_CLASS_OPENING, + SENSOR_NAME_RUNNING: DEVICE_CLASS_POWER, + SENSOR_NAME_BEEP_ENABLED: DEVICE_CLASS_SOUND, + SENSOR_NAME_SCREEN_LOCKED: DEVICE_CLASS_LOCK, +} + +_LOGGER = logging.getLogger(__name__) async def async_setup_entry(hass, entry, async_add_entities): """Set up EcoNet binary sensor based on a config entry.""" equipment = hass.data[DOMAIN][EQUIPMENT][entry.entry_id] binary_sensors = [] - for water_heater in equipment[EquipmentType.WATER_HEATER]: - if water_heater.has_shutoff_valve: - binary_sensors.append( - EcoNetBinarySensor( - water_heater, - SENSOR_NAME_SHUTOFF_VALVE, - ) - ) - if water_heater.running is not None: - binary_sensors.append(EcoNetBinarySensor(water_heater, SENSOR_NAME_RUNNING)) - if water_heater.vacation is not None: - binary_sensors.append( - EcoNetBinarySensor(water_heater, SENSOR_NAME_VACATION) - ) - async_add_entities(binary_sensors) + all_equipment = equipment[EquipmentType.WATER_HEATER] + all_equipment.extend(equipment[EquipmentType.THERMOSTAT]) + for _equip in all_equipment: + for name, attribute in SENSOR_NAMES_TO_ATTRIBUTES.items(): + if getattr(_equip, attribute, None) is not None: + binary_sensors.append(EcoNetBinarySensor(_equip, name)) + async_add_entities( + binary_sensors, + ) class EcoNetBinarySensor(EcoNetEntity, BinarySensorEntity): @@ -52,22 +63,12 @@ def __init__(self, econet_device, device_name): @property def is_on(self): """Return true if the binary sensor is on.""" - if self._device_name == SENSOR_NAME_SHUTOFF_VALVE: - return self._econet.shutoff_valve_open - if self._device_name == SENSOR_NAME_RUNNING: - return self._econet.running - if self._device_name == SENSOR_NAME_VACATION: - return self._econet.vacation - return False + return getattr(self._econet, SENSOR_NAMES_TO_ATTRIBUTES[self._device_name]) @property def device_class(self): """Return the class of this sensor, from DEVICE_CLASSES.""" - if self._device_name == SENSOR_NAME_SHUTOFF_VALVE: - return DEVICE_CLASS_OPENING - if self._device_name == SENSOR_NAME_RUNNING: - return DEVICE_CLASS_POWER - return None + return SENSOR_NAMES_TO_DEVICE_CLASS[self._device_name] @property def name(self): diff --git a/homeassistant/components/econet/climate.py b/homeassistant/components/econet/climate.py new file mode 100644 index 0000000000000..13245999b34dd --- /dev/null +++ b/homeassistant/components/econet/climate.py @@ -0,0 +1,251 @@ +"""Support for Rheem EcoNet thermostats.""" +import logging + +from pyeconet.equipment import EquipmentType +from pyeconet.equipment.thermostat import ThermostatFanMode, ThermostatOperationMode + +from homeassistant.components.climate import ClimateEntity +from homeassistant.components.climate.const import ( + ATTR_TARGET_TEMP_HIGH, + ATTR_TARGET_TEMP_LOW, + FAN_AUTO, + FAN_HIGH, + FAN_LOW, + FAN_MEDIUM, + HVAC_MODE_AUTO, + HVAC_MODE_COOL, + HVAC_MODE_FAN_ONLY, + HVAC_MODE_HEAT, + HVAC_MODE_OFF, + SUPPORT_AUX_HEAT, + SUPPORT_FAN_MODE, + SUPPORT_TARGET_HUMIDITY, + SUPPORT_TARGET_TEMPERATURE, + SUPPORT_TARGET_TEMPERATURE_RANGE, +) +from homeassistant.const import ATTR_TEMPERATURE + +from . import EcoNetEntity +from .const import DOMAIN, EQUIPMENT + +_LOGGER = logging.getLogger(__name__) + +ECONET_STATE_TO_HA = { + ThermostatOperationMode.HEATING: HVAC_MODE_HEAT, + ThermostatOperationMode.COOLING: HVAC_MODE_COOL, + ThermostatOperationMode.OFF: HVAC_MODE_OFF, + ThermostatOperationMode.AUTO: HVAC_MODE_AUTO, + ThermostatOperationMode.FAN_ONLY: HVAC_MODE_FAN_ONLY, +} +HA_STATE_TO_ECONET = {value: key for key, value in ECONET_STATE_TO_HA.items()} + +# TODO: How to handle medlo and medhi +# ThermostatFanMode.MEDHI: FAN_HIGH, +# ThermostatFanMode.MEDLO: FAN_MEDIUM, +ECONET_FAN_STATE_TO_HA = { + ThermostatFanMode.AUTO: FAN_AUTO, + ThermostatFanMode.LOW: FAN_LOW, + ThermostatFanMode.MEDIUM: FAN_MEDIUM, + ThermostatFanMode.HIGH: FAN_HIGH, +} +HA_FAN_STATE_TO_ECONET = {value: key for key, value in ECONET_FAN_STATE_TO_HA.items()} + +SUPPORT_FLAGS_THERMOSTAT = ( + SUPPORT_TARGET_TEMPERATURE + | SUPPORT_TARGET_TEMPERATURE_RANGE + | SUPPORT_FAN_MODE + | SUPPORT_AUX_HEAT +) + + +async def async_setup_entry(hass, entry, async_add_entities): + """Set up EcoNet thermostat based on a config entry.""" + equipment = hass.data[DOMAIN][EQUIPMENT][entry.entry_id] + async_add_entities( + [ + EcoNetThermostat(thermostat) + for thermostat in equipment[EquipmentType.THERMOSTAT] + ], + ) + + +class EcoNetThermostat(EcoNetEntity, ClimateEntity): + """Define a Econet thermostat.""" + + def __init__(self, thermostat): + """Initialize.""" + super().__init__(thermostat) + self._running = thermostat.running + self._poll = True + self.thermostat = thermostat + self.econet_state_to_ha = {} + self.ha_state_to_econet = {} + + @property + def supported_features(self): + """Return the list of supported features.""" + if self.thermostat.supports_humidifier: + return SUPPORT_FLAGS_THERMOSTAT | SUPPORT_TARGET_HUMIDITY + else: + return SUPPORT_FLAGS_THERMOSTAT + + @property + def current_temperature(self): + """Return the current temperature.""" + return self.thermostat.set_point + + @property + def current_humidity(self): + """Return the current humidity.""" + return self.thermostat.humidity + + @property + def target_humidity(self): + """Return the humidity we try to reach.""" + if self.thermostat.supports_humidifier: + return self.thermostat.dehumidifier_set_point + else: + return None + + @property + def target_temperature(self): + """Return the temperature we try to reach.""" + if self.hvac_mode == HVAC_MODE_COOL: + return self.thermostat.cool_set_point + elif self.hvac_mode == HVAC_MODE_HEAT: + return self.thermostat.heat_set_point + else: + return None + + @property + def target_temperature_low(self): + """Return the lower bound temperature we try to reach.""" + if self.hvac_mode == HVAC_MODE_AUTO: + return self.thermostat.heat_set_point + else: + return None + + @property + def target_temperature_high(self): + """Return the higher bound temperature we try to reach.""" + if self.hvac_mode == HVAC_MODE_AUTO: + return self.thermostat.cool_set_point + else: + return None + + def set_temperature(self, **kwargs): + """Set new target temperature.""" + target_temp = kwargs.get(ATTR_TEMPERATURE) + target_temp_low = kwargs.get(ATTR_TARGET_TEMP_LOW) + target_temp_high = kwargs.get(ATTR_TARGET_TEMP_HIGH) + if target_temp: + self.thermostat.set_set_point(target_temp, None, None) + elif target_temp_low or target_temp_high: + self.thermostat.set_set_point(None, target_temp_high, target_temp_low) + else: + _LOGGER.error("Something went wrong") + + @property + def is_aux_heat(self): + """Return true if aux heater.""" + return self.thermostat.mode == ThermostatOperationMode.EMERGENCY_HEAT + + @property + def hvac_modes(self): + """Return hvac operation ie. heat, cool mode. + + Needs to be one of HVAC_MODE_*. + """ + econet_modes = self.thermostat.modes + op_list = [] + for mode in econet_modes: + if mode not in [ + ThermostatOperationMode.UNKNOWN, + ThermostatOperationMode.EMERGENCY_HEAT, + ]: + ha_mode = ECONET_STATE_TO_HA[mode] + op_list.append(ha_mode) + return op_list + + @property + def hvac_mode(self) -> str: + """Return hvac operation ie. heat, cool, mode. + + Needs to be one of HVAC_MODE_*. + """ + econet_mode = self.thermostat.mode + _current_op = HVAC_MODE_OFF + if econet_mode is not None: + _current_op = ECONET_STATE_TO_HA[econet_mode] + + return _current_op + + def set_hvac_mode(self, hvac_mode): + """Set new target hvac mode.""" + hvac_mode_to_set = HA_STATE_TO_ECONET.get(hvac_mode) + self.thermostat.set_mode(hvac_mode_to_set) + + def set_humidity(self, humidity: int): + """Set new target humidity.""" + self.thermostat.set_dehumidifier_set_point(humidity) + + @property + def fan_mode(self): + """Return the current fan mode.""" + econet_fan_mode = self.thermostat.fan_mode + + # Remove this after we figure out how to handle med lo and med hi + if econet_fan_mode in [ThermostatFanMode.MEDHI, ThermostatFanMode.MEDLO]: + econet_fan_mode = ThermostatFanMode.MEDIUM + + _current_fan_mode = FAN_AUTO + if econet_fan_mode is not None: + _current_fan_mode = ECONET_FAN_STATE_TO_HA[econet_fan_mode] + return _current_fan_mode + + @property + def fan_modes(self): + """Return the fan modes.""" + econet_fan_modes = self.thermostat.fan_modes + fan_list = [] + for mode in econet_fan_modes: + # Remove the MEDLO MEDHI once we figure out how to handle it + if mode not in [ + ThermostatFanMode.UNKNOWN, + ThermostatFanMode.MEDLO, + ThermostatFanMode.MEDHI, + ]: + fan_list.append(ECONET_FAN_STATE_TO_HA[mode]) + return fan_list + + def set_fan_mode(self, fan_mode): + """Set the fan mode.""" + self.thermostat.set_fan_mode(HA_FAN_STATE_TO_ECONET[fan_mode]) + + def turn_aux_heat_on(self): + """Turn auxiliary heater on.""" + self.thermostat.set_mode(ThermostatOperationMode.EMERGENCY_HEAT) + + def turn_aux_heat_off(self): + """Turn auxiliary heater off.""" + self.thermostat.set_mode(ThermostatOperationMode.HEATING) + + @property + def min_temp(self): + """Return the minimum temperature.""" + return self.thermostat.set_point_limits[0] + + @property + def max_temp(self): + """Return the maximum temperature.""" + return self.thermostat.set_point_limits[1] + + @property + def min_humidity(self) -> int: + """Return the minimum humidity.""" + return self.thermostat.dehumidifier_set_point_limits[0] + + @property + def max_humidity(self) -> int: + """Return the maximum humidity.""" + return self.thermostat.dehumidifier_set_point_limits[1] diff --git a/homeassistant/components/econet/sensor.py b/homeassistant/components/econet/sensor.py index 6ae14d18aa124..5d04ec4e55022 100644 --- a/homeassistant/components/econet/sensor.py +++ b/homeassistant/components/econet/sensor.py @@ -14,6 +14,7 @@ from .const import DOMAIN, EQUIPMENT ENERGY_KILO_BRITISH_THERMAL_UNIT = "kBtu" + TANK_HEALTH = "tank_health" AVAILIBLE_HOT_WATER = "availible_hot_water" COMPRESSOR_HEALTH = "compressor_health" @@ -24,32 +25,58 @@ WIFI_SIGNAL = "wifi_signal" RUNNING_STATE = "running_state" +SENSOR_NAMES_TO_ATTRIBUTES = { + TANK_HEALTH: "tank_health", + AVAILIBLE_HOT_WATER: "tank_hot_water_availability", + COMPRESSOR_HEALTH: "compressor_health", + OVERRIDE_STATUS: "override_status", + WATER_USAGE_TODAY: "todays_water_usage", + POWER_USAGE_TODAY: "todays_energy_usage", + ALERT_COUNT: "alert_count", + WIFI_SIGNAL: "wifi_signal", + RUNNING_STATE: "running_state", +} + +SENSOR_NAMES_TO_UNIT_OF_MEASUREMENT = { + TANK_HEALTH: PERCENTAGE, + AVAILIBLE_HOT_WATER: PERCENTAGE, + COMPRESSOR_HEALTH: PERCENTAGE, + OVERRIDE_STATUS: None, + WATER_USAGE_TODAY: VOLUME_GALLONS, + POWER_USAGE_TODAY: None, # Depends on unit type + ALERT_COUNT: None, + WIFI_SIGNAL: SIGNAL_STRENGTH_DECIBELS_MILLIWATT, + RUNNING_STATE: None, # This is just a string +} + _LOGGER = logging.getLogger(__name__) async def async_setup_entry(hass, entry, async_add_entities): """Set up EcoNet sensor based on a config entry.""" + equipment = hass.data[DOMAIN][EQUIPMENT][entry.entry_id] sensors = [] + all_equipment = equipment[EquipmentType.WATER_HEATER] + all_equipment.extend(equipment[EquipmentType.THERMOSTAT]) + equipment = hass.data[DOMAIN][EQUIPMENT][entry.entry_id] + + for _equip in all_equipment: + for name, attribute in SENSOR_NAMES_TO_ATTRIBUTES.items(): + if getattr(_equip, attribute, None) is not None: + sensors.append(EcoNetSensor(_equip, name)) + # This is None to start with and all device have it + sensors.append(EcoNetSensor(_equip, WIFI_SIGNAL)) + for water_heater in equipment[EquipmentType.WATER_HEATER]: - if water_heater.tank_hot_water_availability is not None: - sensors.append(EcoNetSensor(water_heater, AVAILIBLE_HOT_WATER)) - if water_heater.tank_health is not None: - sensors.append(EcoNetSensor(water_heater, TANK_HEALTH)) - if water_heater.compressor_health is not None: - sensors.append(EcoNetSensor(water_heater, COMPRESSOR_HEALTH)) - if water_heater.override_status: - sensors.append(EcoNetSensor(water_heater, OVERRIDE_STATUS)) - if water_heater.running_state is not None: - sensors.append(EcoNetSensor(water_heater, RUNNING_STATE)) - # All units have this - sensors.append(EcoNetSensor(water_heater, ALERT_COUNT)) # These aren't part of the device and start off as None in pyeconet so always add them sensors.append(EcoNetSensor(water_heater, WATER_USAGE_TODAY)) sensors.append(EcoNetSensor(water_heater, POWER_USAGE_TODAY)) - sensors.append(EcoNetSensor(water_heater, WIFI_SIGNAL)) - async_add_entities(sensors) + + async_add_entities( + sensors, + ) class EcoNetSensor(EcoNetEntity): @@ -64,50 +91,21 @@ def __init__(self, econet_device, device_name): @property def state(self): """Return sensors state.""" - if self._device_name == AVAILIBLE_HOT_WATER: - return self._econet.tank_hot_water_availability - if self._device_name == TANK_HEALTH: - return self._econet.tank_health - if self._device_name == COMPRESSOR_HEALTH: - return self._econet.compressor_health - if self._device_name == OVERRIDE_STATUS: - return self._econet.oveerride_status - if self._device_name == WATER_USAGE_TODAY: - if self._econet.todays_water_usage: - return round(self._econet.todays_water_usage, 2) - return None - if self._device_name == POWER_USAGE_TODAY: - if self._econet.todays_energy_usage: - return round(self._econet.todays_energy_usage, 2) - return None - if self._device_name == WIFI_SIGNAL: - if self._econet.wifi_signal: - return self._econet.wifi_signal - return None - if self._device_name == ALERT_COUNT: - return self._econet.alert_count - if self._device_name == RUNNING_STATE: - return self._econet.running_state - return None + value = getattr(self._econet, SENSOR_NAMES_TO_ATTRIBUTES[self._device_name]) + if value is float: + value = round(value, 2) + return value @property def unit_of_measurement(self): """Return the unit of measurement of this entity, if any.""" - if self._device_name == AVAILIBLE_HOT_WATER: - return PERCENTAGE - if self._device_name == TANK_HEALTH: - return PERCENTAGE - if self._device_name == COMPRESSOR_HEALTH: - return PERCENTAGE - if self._device_name == WATER_USAGE_TODAY: - return VOLUME_GALLONS + unit_of_measurement = SENSOR_NAMES_TO_UNIT_OF_MEASUREMENT[self._device_name] if self._device_name == POWER_USAGE_TODAY: if self._econet.energy_type == ENERGY_KILO_BRITISH_THERMAL_UNIT.upper(): - return ENERGY_KILO_BRITISH_THERMAL_UNIT - return ENERGY_KILO_WATT_HOUR - if self._device_name == WIFI_SIGNAL: - return SIGNAL_STRENGTH_DECIBELS_MILLIWATT - return None + unit_of_measurement = ENERGY_KILO_BRITISH_THERMAL_UNIT + else: + unit_of_measurement = ENERGY_KILO_WATT_HOUR + return unit_of_measurement @property def name(self): From d8f5dcef37781c1f546656b1767f7cc8f5d2c7f5 Mon Sep 17 00:00:00 2001 From: w1ll1am23 Date: Tue, 26 Jan 2021 15:28:04 +0000 Subject: [PATCH 02/12] Removed unnecessary elses --- homeassistant/components/econet/climate.py | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/homeassistant/components/econet/climate.py b/homeassistant/components/econet/climate.py index 13245999b34dd..83945b6d99e08 100644 --- a/homeassistant/components/econet/climate.py +++ b/homeassistant/components/econet/climate.py @@ -86,8 +86,7 @@ def supported_features(self): """Return the list of supported features.""" if self.thermostat.supports_humidifier: return SUPPORT_FLAGS_THERMOSTAT | SUPPORT_TARGET_HUMIDITY - else: - return SUPPORT_FLAGS_THERMOSTAT + return SUPPORT_FLAGS_THERMOSTAT @property def current_temperature(self): @@ -104,8 +103,7 @@ def target_humidity(self): """Return the humidity we try to reach.""" if self.thermostat.supports_humidifier: return self.thermostat.dehumidifier_set_point - else: - return None + return None @property def target_temperature(self): @@ -114,24 +112,21 @@ def target_temperature(self): return self.thermostat.cool_set_point elif self.hvac_mode == HVAC_MODE_HEAT: return self.thermostat.heat_set_point - else: - return None + return None @property def target_temperature_low(self): """Return the lower bound temperature we try to reach.""" if self.hvac_mode == HVAC_MODE_AUTO: return self.thermostat.heat_set_point - else: - return None + return None @property def target_temperature_high(self): """Return the higher bound temperature we try to reach.""" if self.hvac_mode == HVAC_MODE_AUTO: return self.thermostat.cool_set_point - else: - return None + return None def set_temperature(self, **kwargs): """Set new target temperature.""" From 637da9002281a67a606e340cfb353f01ad7a0a8e Mon Sep 17 00:00:00 2001 From: w1ll1am23 Date: Sun, 31 Jan 2021 01:31:58 +0000 Subject: [PATCH 03/12] Fixed crash and bump pyeconet to fix set point limits --- homeassistant/components/econet/__init__.py | 4 +++- homeassistant/components/econet/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/econet/__init__.py b/homeassistant/components/econet/__init__.py index fddd238051f9f..053d34cf7f254 100644 --- a/homeassistant/components/econet/__init__.py +++ b/homeassistant/components/econet/__init__.py @@ -54,7 +54,9 @@ async def async_setup_entry(hass, config_entry): raise ConfigEntryNotReady from err try: - equipment = await api.get_equipment_by_type([EquipmentType.WATER_HEATER]) + equipment = await api.get_equipment_by_type( + [EquipmentType.WATER_HEATER, EquipmentType.THERMOSTAT] + ) except (ClientError, GenericHTTPError, InvalidResponseFormat) as err: raise ConfigEntryNotReady from err hass.data[DOMAIN][API_CLIENT][config_entry.entry_id] = api diff --git a/homeassistant/components/econet/manifest.json b/homeassistant/components/econet/manifest.json index 7e4cf0106ba22..abc5f9e3e13f5 100644 --- a/homeassistant/components/econet/manifest.json +++ b/homeassistant/components/econet/manifest.json @@ -4,6 +4,6 @@ "name": "Rheem EcoNet Products", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/econet", - "requirements": ["pyeconet==0.1.12"], + "requirements": ["pyeconet==0.1.13b1"], "codeowners": ["@vangorra", "@w1ll1am23"] } \ No newline at end of file diff --git a/requirements_all.txt b/requirements_all.txt index d2342e4da95fd..af267ed7131b3 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1355,7 +1355,7 @@ pydroid-ipcam==0.8 pyebox==1.1.4 # homeassistant.components.econet -pyeconet==0.1.12 +pyeconet==0.1.13b1 # homeassistant.components.edimax pyedimax==0.2.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 5e1b0f26d1c98..d30e3ce3ab712 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -685,7 +685,7 @@ pydexcom==0.2.0 pydispatcher==2.0.5 # homeassistant.components.econet -pyeconet==0.1.12 +pyeconet==0.1.13b1 # homeassistant.components.everlights pyeverlights==0.1.0 From 376f829a0d41f1e4424aa7528e7e360c7e5b7fcb Mon Sep 17 00:00:00 2001 From: w1ll1am23 Date: Sun, 31 Jan 2021 02:48:45 +0000 Subject: [PATCH 04/12] Fixed temperature unit crash --- homeassistant/components/econet/__init__.py | 7 ++++++- homeassistant/components/econet/sensor.py | 1 - homeassistant/components/econet/water_heater.py | 6 ------ 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/homeassistant/components/econet/__init__.py b/homeassistant/components/econet/__init__.py index 053d34cf7f254..3b3e83072341d 100644 --- a/homeassistant/components/econet/__init__.py +++ b/homeassistant/components/econet/__init__.py @@ -13,7 +13,7 @@ PyeconetError, ) -from homeassistant.const import CONF_EMAIL, CONF_PASSWORD +from homeassistant.const import CONF_EMAIL, CONF_PASSWORD, TEMP_FAHRENHEIT from homeassistant.core import callback from homeassistant.exceptions import ConfigEntryNotReady from homeassistant.helpers.dispatcher import dispatcher_send @@ -151,6 +151,11 @@ def unique_id(self): """Return the unique ID of the entity.""" return f"{self._econet.device_id}_{self._econet.device_name}" + @property + def temperature_unit(self): + """Return the unit of measurement.""" + return TEMP_FAHRENHEIT + @property def should_poll(self) -> bool: """Return True if entity has to be polled for state. diff --git a/homeassistant/components/econet/sensor.py b/homeassistant/components/econet/sensor.py index 5d04ec4e55022..828268c8363a1 100644 --- a/homeassistant/components/econet/sensor.py +++ b/homeassistant/components/econet/sensor.py @@ -60,7 +60,6 @@ async def async_setup_entry(hass, entry, async_add_entities): sensors = [] all_equipment = equipment[EquipmentType.WATER_HEATER] all_equipment.extend(equipment[EquipmentType.THERMOSTAT]) - equipment = hass.data[DOMAIN][EQUIPMENT][entry.entry_id] for _equip in all_equipment: for name, attribute in SENSOR_NAMES_TO_ATTRIBUTES.items(): diff --git a/homeassistant/components/econet/water_heater.py b/homeassistant/components/econet/water_heater.py index af3399b53afb3..f54cc02eafb44 100644 --- a/homeassistant/components/econet/water_heater.py +++ b/homeassistant/components/econet/water_heater.py @@ -18,7 +18,6 @@ SUPPORT_TARGET_TEMPERATURE, WaterHeaterEntity, ) -from homeassistant.const import TEMP_FAHRENHEIT from homeassistant.core import callback from . import EcoNetEntity @@ -77,11 +76,6 @@ def is_away_mode_on(self): """Return true if away mode is on.""" return self._econet.away - @property - def temperature_unit(self): - """Return the unit of measurement.""" - return TEMP_FAHRENHEIT - @property def current_operation(self): """Return current operation.""" From 6c243bb75433ecf3e4759839c3a727514d20c2a3 Mon Sep 17 00:00:00 2001 From: w1ll1am23 Date: Sun, 31 Jan 2021 15:41:11 +0000 Subject: [PATCH 05/12] Fixed sensor creation duplication issue. Fixed running state in pyeonet version and set thermostats to get push updates --- homeassistant/components/econet/__init__.py | 3 +++ homeassistant/components/econet/binary_sensor.py | 4 ++-- homeassistant/components/econet/manifest.json | 2 +- homeassistant/components/econet/sensor.py | 4 ++-- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 6 files changed, 10 insertions(+), 7 deletions(-) diff --git a/homeassistant/components/econet/__init__.py b/homeassistant/components/econet/__init__.py index 3b3e83072341d..d31ff20b02f49 100644 --- a/homeassistant/components/econet/__init__.py +++ b/homeassistant/components/econet/__init__.py @@ -76,6 +76,9 @@ def update_published(): for _eqip in equipment[EquipmentType.WATER_HEATER]: _eqip.set_update_callback(update_published) + for _eqip in equipment[EquipmentType.THERMOSTAT]: + _eqip.set_update_callback(update_published) + async def resubscribe(now): """Resubscribe to the MQTT updates.""" await hass.async_add_executor_job(api.unsubscribe) diff --git a/homeassistant/components/econet/binary_sensor.py b/homeassistant/components/econet/binary_sensor.py index 49628c4a4845c..75eda8a1ce11e 100644 --- a/homeassistant/components/econet/binary_sensor.py +++ b/homeassistant/components/econet/binary_sensor.py @@ -40,8 +40,8 @@ async def async_setup_entry(hass, entry, async_add_entities): """Set up EcoNet binary sensor based on a config entry.""" equipment = hass.data[DOMAIN][EQUIPMENT][entry.entry_id] binary_sensors = [] - all_equipment = equipment[EquipmentType.WATER_HEATER] - all_equipment.extend(equipment[EquipmentType.THERMOSTAT]) + all_equipment = equipment[EquipmentType.WATER_HEATER].copy() + all_equipment.extend(equipment[EquipmentType.THERMOSTAT].copy()) for _equip in all_equipment: for name, attribute in SENSOR_NAMES_TO_ATTRIBUTES.items(): if getattr(_equip, attribute, None) is not None: diff --git a/homeassistant/components/econet/manifest.json b/homeassistant/components/econet/manifest.json index abc5f9e3e13f5..c658542295e86 100644 --- a/homeassistant/components/econet/manifest.json +++ b/homeassistant/components/econet/manifest.json @@ -4,6 +4,6 @@ "name": "Rheem EcoNet Products", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/econet", - "requirements": ["pyeconet==0.1.13b1"], + "requirements": ["pyeconet==0.1.13"], "codeowners": ["@vangorra", "@w1ll1am23"] } \ No newline at end of file diff --git a/homeassistant/components/econet/sensor.py b/homeassistant/components/econet/sensor.py index 828268c8363a1..706ddba4b8b84 100644 --- a/homeassistant/components/econet/sensor.py +++ b/homeassistant/components/econet/sensor.py @@ -58,8 +58,8 @@ async def async_setup_entry(hass, entry, async_add_entities): equipment = hass.data[DOMAIN][EQUIPMENT][entry.entry_id] sensors = [] - all_equipment = equipment[EquipmentType.WATER_HEATER] - all_equipment.extend(equipment[EquipmentType.THERMOSTAT]) + all_equipment = equipment[EquipmentType.WATER_HEATER].copy() + all_equipment.extend(equipment[EquipmentType.THERMOSTAT].copy()) for _equip in all_equipment: for name, attribute in SENSOR_NAMES_TO_ATTRIBUTES.items(): diff --git a/requirements_all.txt b/requirements_all.txt index af267ed7131b3..ae67468a26879 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1355,7 +1355,7 @@ pydroid-ipcam==0.8 pyebox==1.1.4 # homeassistant.components.econet -pyeconet==0.1.13b1 +pyeconet==0.1.13 # homeassistant.components.edimax pyedimax==0.2.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index d30e3ce3ab712..a01228ccea94a 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -685,7 +685,7 @@ pydexcom==0.2.0 pydispatcher==2.0.5 # homeassistant.components.econet -pyeconet==0.1.13b1 +pyeconet==0.1.13 # homeassistant.components.everlights pyeverlights==0.1.0 From 26936d230703f9865f9ffd9edfe03579ad11aa8c Mon Sep 17 00:00:00 2001 From: w1ll1am23 Date: Mon, 1 Feb 2021 15:10:06 +0000 Subject: [PATCH 06/12] Fixed lint and removed TODO --- homeassistant/components/econet/climate.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/homeassistant/components/econet/climate.py b/homeassistant/components/econet/climate.py index 83945b6d99e08..a38be286842cb 100644 --- a/homeassistant/components/econet/climate.py +++ b/homeassistant/components/econet/climate.py @@ -39,9 +39,6 @@ } HA_STATE_TO_ECONET = {value: key for key, value in ECONET_STATE_TO_HA.items()} -# TODO: How to handle medlo and medhi -# ThermostatFanMode.MEDHI: FAN_HIGH, -# ThermostatFanMode.MEDLO: FAN_MEDIUM, ECONET_FAN_STATE_TO_HA = { ThermostatFanMode.AUTO: FAN_AUTO, ThermostatFanMode.LOW: FAN_LOW, @@ -110,7 +107,7 @@ def target_temperature(self): """Return the temperature we try to reach.""" if self.hvac_mode == HVAC_MODE_COOL: return self.thermostat.cool_set_point - elif self.hvac_mode == HVAC_MODE_HEAT: + if self.hvac_mode == HVAC_MODE_HEAT: return self.thermostat.heat_set_point return None @@ -135,10 +132,10 @@ def set_temperature(self, **kwargs): target_temp_high = kwargs.get(ATTR_TARGET_TEMP_HIGH) if target_temp: self.thermostat.set_set_point(target_temp, None, None) - elif target_temp_low or target_temp_high: + return + if target_temp_low or target_temp_high: self.thermostat.set_set_point(None, target_temp_high, target_temp_low) - else: - _LOGGER.error("Something went wrong") + return @property def is_aux_heat(self): From ce9162157ee0adc017b28244cc4249e7633829df Mon Sep 17 00:00:00 2001 From: William Scanlon Date: Sun, 21 Mar 2021 13:00:19 -0400 Subject: [PATCH 07/12] Remove logger from binary_sensor.py --- homeassistant/components/econet/binary_sensor.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/homeassistant/components/econet/binary_sensor.py b/homeassistant/components/econet/binary_sensor.py index 3c54d0e22b6e6..41641d21e31a0 100644 --- a/homeassistant/components/econet/binary_sensor.py +++ b/homeassistant/components/econet/binary_sensor.py @@ -32,8 +32,6 @@ SENSOR_NAME_SCREEN_LOCKED: DEVICE_CLASS_LOCK, } -_LOGGER = logging.getLogger(__name__) - async def async_setup_entry(hass, entry, async_add_entities): """Set up EcoNet binary sensor based on a config entry.""" From 511146cc5104d60d302564d7334a02e63ce578d2 Mon Sep 17 00:00:00 2001 From: w1ll1am23 Date: Wed, 24 Mar 2021 22:39:17 +0000 Subject: [PATCH 08/12] Addressed PR comments --- .../components/econet/binary_sensor.py | 37 +++++---- homeassistant/components/econet/climate.py | 78 +++++++++---------- homeassistant/components/econet/sensor.py | 10 +-- .../components/econet/water_heater.py | 1 + 4 files changed, 64 insertions(+), 62 deletions(-) diff --git a/homeassistant/components/econet/binary_sensor.py b/homeassistant/components/econet/binary_sensor.py index 75eda8a1ce11e..4585bbef74ba4 100644 --- a/homeassistant/components/econet/binary_sensor.py +++ b/homeassistant/components/econet/binary_sensor.py @@ -19,18 +19,22 @@ SENSOR_NAME_SCREEN_LOCKED = "screen_locked" SENSOR_NAME_BEEP_ENABLED = "beep_enabled" -SENSOR_NAMES_TO_ATTRIBUTES = { - SENSOR_NAME_SHUTOFF_VALVE: "shutoff_valve_open", - SENSOR_NAME_RUNNING: "running", - SENSOR_NAME_SCREEN_LOCKED: "screen_locked", - SENSOR_NAME_BEEP_ENABLED: "beep_enabled", -} - -SENSOR_NAMES_TO_DEVICE_CLASS = { - SENSOR_NAME_SHUTOFF_VALVE: DEVICE_CLASS_OPENING, - SENSOR_NAME_RUNNING: DEVICE_CLASS_POWER, - SENSOR_NAME_BEEP_ENABLED: DEVICE_CLASS_SOUND, - SENSOR_NAME_SCREEN_LOCKED: DEVICE_CLASS_LOCK, +ATTR = "attr" +DEVICE_CLASS = "device_class" +SENSORS = { + SENSOR_NAME_SHUTOFF_VALVE: { + ATTR: "shutoff_valve_open", + DEVICE_CLASS: DEVICE_CLASS_OPENING, + }, + SENSOR_NAME_RUNNING: {ATTR: "running", DEVICE_CLASS: DEVICE_CLASS_POWER}, + SENSOR_NAME_SCREEN_LOCKED: { + ATTR: "screen_locked", + DEVICE_CLASS: DEVICE_CLASS_LOCK, + }, + SENSOR_NAME_BEEP_ENABLED: { + ATTR: "beep_enabled", + DEVICE_CLASS: DEVICE_CLASS_SOUND, + }, } _LOGGER = logging.getLogger(__name__) @@ -43,7 +47,10 @@ async def async_setup_entry(hass, entry, async_add_entities): all_equipment = equipment[EquipmentType.WATER_HEATER].copy() all_equipment.extend(equipment[EquipmentType.THERMOSTAT].copy()) for _equip in all_equipment: - for name, attribute in SENSOR_NAMES_TO_ATTRIBUTES.items(): + attributes = [] + for sensor in SENSORS.values(): + attributes.append(sensor[ATTR]) + for name, attribute in attributes: if getattr(_equip, attribute, None) is not None: binary_sensors.append(EcoNetBinarySensor(_equip, name)) async_add_entities( @@ -63,12 +70,12 @@ def __init__(self, econet_device, device_name): @property def is_on(self): """Return true if the binary sensor is on.""" - return getattr(self._econet, SENSOR_NAMES_TO_ATTRIBUTES[self._device_name]) + return getattr(self._econet, SENSORS[self._device_name][ATTR]) @property def device_class(self): """Return the class of this sensor, from DEVICE_CLASSES.""" - return SENSOR_NAMES_TO_DEVICE_CLASS[self._device_name] + return SENSORS[self._device_name][DEVICE_CLASS] @property def name(self): diff --git a/homeassistant/components/econet/climate.py b/homeassistant/components/econet/climate.py index a38be286842cb..9233bc82c3572 100644 --- a/homeassistant/components/econet/climate.py +++ b/homeassistant/components/econet/climate.py @@ -12,10 +12,10 @@ FAN_HIGH, FAN_LOW, FAN_MEDIUM, - HVAC_MODE_AUTO, HVAC_MODE_COOL, HVAC_MODE_FAN_ONLY, HVAC_MODE_HEAT, + HVAC_MODE_HEAT_COOL, HVAC_MODE_OFF, SUPPORT_AUX_HEAT, SUPPORT_FAN_MODE, @@ -34,7 +34,7 @@ ThermostatOperationMode.HEATING: HVAC_MODE_HEAT, ThermostatOperationMode.COOLING: HVAC_MODE_COOL, ThermostatOperationMode.OFF: HVAC_MODE_OFF, - ThermostatOperationMode.AUTO: HVAC_MODE_AUTO, + ThermostatOperationMode.AUTO: HVAC_MODE_HEAT_COOL, ThermostatOperationMode.FAN_ONLY: HVAC_MODE_FAN_ONLY, } HA_STATE_TO_ECONET = {value: key for key, value in ECONET_STATE_TO_HA.items()} @@ -74,55 +74,62 @@ def __init__(self, thermostat): super().__init__(thermostat) self._running = thermostat.running self._poll = True - self.thermostat = thermostat self.econet_state_to_ha = {} self.ha_state_to_econet = {} + self.op_list = [] + for mode in self._econet.modes: + if mode not in [ + ThermostatOperationMode.UNKNOWN, + ThermostatOperationMode.EMERGENCY_HEAT, + ]: + ha_mode = ECONET_STATE_TO_HA[mode] + self.op_list.append(ha_mode) @property def supported_features(self): """Return the list of supported features.""" - if self.thermostat.supports_humidifier: + if self._econet.supports_humidifier: return SUPPORT_FLAGS_THERMOSTAT | SUPPORT_TARGET_HUMIDITY return SUPPORT_FLAGS_THERMOSTAT @property def current_temperature(self): """Return the current temperature.""" - return self.thermostat.set_point + return self._econet.set_point @property def current_humidity(self): """Return the current humidity.""" - return self.thermostat.humidity + return self._econet.humidity @property def target_humidity(self): """Return the humidity we try to reach.""" - if self.thermostat.supports_humidifier: - return self.thermostat.dehumidifier_set_point + if self._econet.supports_humidifier: + return self._econet.dehumidifier_set_point return None @property def target_temperature(self): """Return the temperature we try to reach.""" if self.hvac_mode == HVAC_MODE_COOL: - return self.thermostat.cool_set_point + return self._econet.cool_set_point if self.hvac_mode == HVAC_MODE_HEAT: - return self.thermostat.heat_set_point + return self._econet.heat_set_point return None @property def target_temperature_low(self): """Return the lower bound temperature we try to reach.""" - if self.hvac_mode == HVAC_MODE_AUTO: - return self.thermostat.heat_set_point + if self.hvac_mode == HVAC_MODE_HEAT_COOL: + return self._econet.heat_set_point return None @property def target_temperature_high(self): """Return the higher bound temperature we try to reach.""" - if self.hvac_mode == HVAC_MODE_AUTO: - return self.thermostat.cool_set_point + if self.hvac_mode == HVAC_MODE_HEAT_COOL: + return self._econet.cool_set_point return None def set_temperature(self, **kwargs): @@ -131,16 +138,14 @@ def set_temperature(self, **kwargs): target_temp_low = kwargs.get(ATTR_TARGET_TEMP_LOW) target_temp_high = kwargs.get(ATTR_TARGET_TEMP_HIGH) if target_temp: - self.thermostat.set_set_point(target_temp, None, None) - return + self._econet.set_set_point(target_temp, None, None) if target_temp_low or target_temp_high: - self.thermostat.set_set_point(None, target_temp_high, target_temp_low) - return + self._econet.set_set_point(None, target_temp_high, target_temp_low) @property def is_aux_heat(self): """Return true if aux heater.""" - return self.thermostat.mode == ThermostatOperationMode.EMERGENCY_HEAT + return self._econet.mode == ThermostatOperationMode.EMERGENCY_HEAT @property def hvac_modes(self): @@ -148,16 +153,7 @@ def hvac_modes(self): Needs to be one of HVAC_MODE_*. """ - econet_modes = self.thermostat.modes - op_list = [] - for mode in econet_modes: - if mode not in [ - ThermostatOperationMode.UNKNOWN, - ThermostatOperationMode.EMERGENCY_HEAT, - ]: - ha_mode = ECONET_STATE_TO_HA[mode] - op_list.append(ha_mode) - return op_list + return self.op_list @property def hvac_mode(self) -> str: @@ -165,7 +161,7 @@ def hvac_mode(self) -> str: Needs to be one of HVAC_MODE_*. """ - econet_mode = self.thermostat.mode + econet_mode = self.econet.mode _current_op = HVAC_MODE_OFF if econet_mode is not None: _current_op = ECONET_STATE_TO_HA[econet_mode] @@ -175,16 +171,16 @@ def hvac_mode(self) -> str: def set_hvac_mode(self, hvac_mode): """Set new target hvac mode.""" hvac_mode_to_set = HA_STATE_TO_ECONET.get(hvac_mode) - self.thermostat.set_mode(hvac_mode_to_set) + self.econet.set_mode(hvac_mode_to_set) def set_humidity(self, humidity: int): """Set new target humidity.""" - self.thermostat.set_dehumidifier_set_point(humidity) + self.econet.set_dehumidifier_set_point(humidity) @property def fan_mode(self): """Return the current fan mode.""" - econet_fan_mode = self.thermostat.fan_mode + econet_fan_mode = self.econet.fan_mode # Remove this after we figure out how to handle med lo and med hi if econet_fan_mode in [ThermostatFanMode.MEDHI, ThermostatFanMode.MEDLO]: @@ -198,7 +194,7 @@ def fan_mode(self): @property def fan_modes(self): """Return the fan modes.""" - econet_fan_modes = self.thermostat.fan_modes + econet_fan_modes = self.econet.fan_modes fan_list = [] for mode in econet_fan_modes: # Remove the MEDLO MEDHI once we figure out how to handle it @@ -212,32 +208,32 @@ def fan_modes(self): def set_fan_mode(self, fan_mode): """Set the fan mode.""" - self.thermostat.set_fan_mode(HA_FAN_STATE_TO_ECONET[fan_mode]) + self._econet.set_fan_mode(HA_FAN_STATE_TO_ECONET[fan_mode]) def turn_aux_heat_on(self): """Turn auxiliary heater on.""" - self.thermostat.set_mode(ThermostatOperationMode.EMERGENCY_HEAT) + self._econet.set_mode(ThermostatOperationMode.EMERGENCY_HEAT) def turn_aux_heat_off(self): """Turn auxiliary heater off.""" - self.thermostat.set_mode(ThermostatOperationMode.HEATING) + self._econet.set_mode(ThermostatOperationMode.HEATING) @property def min_temp(self): """Return the minimum temperature.""" - return self.thermostat.set_point_limits[0] + return self._econet.set_point_limits[0] @property def max_temp(self): """Return the maximum temperature.""" - return self.thermostat.set_point_limits[1] + return self._econet.set_point_limits[1] @property def min_humidity(self) -> int: """Return the minimum humidity.""" - return self.thermostat.dehumidifier_set_point_limits[0] + return self._econet.dehumidifier_set_point_limits[0] @property def max_humidity(self) -> int: """Return the maximum humidity.""" - return self.thermostat.dehumidifier_set_point_limits[1] + return self._econet.dehumidifier_set_point_limits[1] diff --git a/homeassistant/components/econet/sensor.py b/homeassistant/components/econet/sensor.py index 706ddba4b8b84..17465fbf44e88 100644 --- a/homeassistant/components/econet/sensor.py +++ b/homeassistant/components/econet/sensor.py @@ -6,7 +6,7 @@ from homeassistant.const import ( ENERGY_KILO_WATT_HOUR, PERCENTAGE, - SIGNAL_STRENGTH_DECIBELS_MILLIWATT, + SIGNAL_STRENGTH, VOLUME_GALLONS, ) @@ -45,7 +45,7 @@ WATER_USAGE_TODAY: VOLUME_GALLONS, POWER_USAGE_TODAY: None, # Depends on unit type ALERT_COUNT: None, - WIFI_SIGNAL: SIGNAL_STRENGTH_DECIBELS_MILLIWATT, + WIFI_SIGNAL: SIGNAL_STRENGTH, RUNNING_STATE: None, # This is just a string } @@ -73,9 +73,7 @@ async def async_setup_entry(hass, entry, async_add_entities): sensors.append(EcoNetSensor(water_heater, WATER_USAGE_TODAY)) sensors.append(EcoNetSensor(water_heater, POWER_USAGE_TODAY)) - async_add_entities( - sensors, - ) + async_add_entities(sensors) class EcoNetSensor(EcoNetEntity): @@ -91,7 +89,7 @@ def __init__(self, econet_device, device_name): def state(self): """Return sensors state.""" value = getattr(self._econet, SENSOR_NAMES_TO_ATTRIBUTES[self._device_name]) - if value is float: + if isinstance(value, float): value = round(value, 2) return value diff --git a/homeassistant/components/econet/water_heater.py b/homeassistant/components/econet/water_heater.py index f54cc02eafb44..ed31e78af7c2a 100644 --- a/homeassistant/components/econet/water_heater.py +++ b/homeassistant/components/econet/water_heater.py @@ -154,6 +154,7 @@ 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): From f665c580841d97faf04414a2bef69212ee048356 Mon Sep 17 00:00:00 2001 From: w1ll1am23 Date: Wed, 24 Mar 2021 22:52:19 +0000 Subject: [PATCH 09/12] Raise value error when mode is None --- homeassistant/components/econet/binary_sensor.py | 11 +++++------ homeassistant/components/econet/climate.py | 12 +++++++----- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/homeassistant/components/econet/binary_sensor.py b/homeassistant/components/econet/binary_sensor.py index c4bb886502042..91e2c046d2ba8 100644 --- a/homeassistant/components/econet/binary_sensor.py +++ b/homeassistant/components/econet/binary_sensor.py @@ -43,16 +43,15 @@ async def async_setup_entry(hass, entry, async_add_entities): binary_sensors = [] all_equipment = equipment[EquipmentType.WATER_HEATER].copy() all_equipment.extend(equipment[EquipmentType.THERMOSTAT].copy()) + attributes = [] + for sensor in SENSORS.values(): + attributes.append(sensor[ATTR]) for _equip in all_equipment: - attributes = [] - for sensor in SENSORS.values(): - attributes.append(sensor[ATTR]) for name, attribute in attributes: if getattr(_equip, attribute, None) is not None: binary_sensors.append(EcoNetBinarySensor(_equip, name)) - async_add_entities( - binary_sensors, - ) + + async_add_entities(binary_sensors) class EcoNetBinarySensor(EcoNetEntity, BinarySensorEntity): diff --git a/homeassistant/components/econet/climate.py b/homeassistant/components/econet/climate.py index 9233bc82c3572..fe50855d55936 100644 --- a/homeassistant/components/econet/climate.py +++ b/homeassistant/components/econet/climate.py @@ -161,7 +161,7 @@ def hvac_mode(self) -> str: Needs to be one of HVAC_MODE_*. """ - econet_mode = self.econet.mode + econet_mode = self._econet.mode _current_op = HVAC_MODE_OFF if econet_mode is not None: _current_op = ECONET_STATE_TO_HA[econet_mode] @@ -171,16 +171,18 @@ def hvac_mode(self) -> str: def set_hvac_mode(self, hvac_mode): """Set new target hvac mode.""" hvac_mode_to_set = HA_STATE_TO_ECONET.get(hvac_mode) - self.econet.set_mode(hvac_mode_to_set) + if hvac_mode_to_set is None: + raise ValueError(f"{hvac_mode} is not a valid mode.") + self._econet.set_mode(hvac_mode_to_set) def set_humidity(self, humidity: int): """Set new target humidity.""" - self.econet.set_dehumidifier_set_point(humidity) + self._econet.set_dehumidifier_set_point(humidity) @property def fan_mode(self): """Return the current fan mode.""" - econet_fan_mode = self.econet.fan_mode + econet_fan_mode = self._econet.fan_mode # Remove this after we figure out how to handle med lo and med hi if econet_fan_mode in [ThermostatFanMode.MEDHI, ThermostatFanMode.MEDLO]: @@ -194,7 +196,7 @@ def fan_mode(self): @property def fan_modes(self): """Return the fan modes.""" - econet_fan_modes = self.econet.fan_modes + econet_fan_modes = self._econet.fan_modes fan_list = [] for mode in econet_fan_modes: # Remove the MEDLO MEDHI once we figure out how to handle it From d9f091cbb9db361841213b97ff5d872e7a7e9fbb Mon Sep 17 00:00:00 2001 From: w1ll1am23 Date: Wed, 24 Mar 2021 23:07:38 +0000 Subject: [PATCH 10/12] Fix signal strength --- homeassistant/components/econet/sensor.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/econet/sensor.py b/homeassistant/components/econet/sensor.py index a89964e11f9a7..aa4df0035cff0 100644 --- a/homeassistant/components/econet/sensor.py +++ b/homeassistant/components/econet/sensor.py @@ -2,9 +2,9 @@ from pyeconet.equipment import EquipmentType from homeassistant.const import ( + DEVICE_CLASS_SIGNAL_STRENGTH, ENERGY_KILO_WATT_HOUR, PERCENTAGE, - SIGNAL_STRENGTH, VOLUME_GALLONS, ) @@ -43,7 +43,7 @@ WATER_USAGE_TODAY: VOLUME_GALLONS, POWER_USAGE_TODAY: None, # Depends on unit type ALERT_COUNT: None, - WIFI_SIGNAL: SIGNAL_STRENGTH, + WIFI_SIGNAL: DEVICE_CLASS_SIGNAL_STRENGTH, RUNNING_STATE: None, # This is just a string } From a4aabfb9b588e89f396a54dabcc2a081217f5705 Mon Sep 17 00:00:00 2001 From: William Scanlon Date: Thu, 25 Mar 2021 09:53:16 -0400 Subject: [PATCH 11/12] Update homeassistant/components/econet/binary_sensor.py Co-authored-by: Martin Hjelmare --- homeassistant/components/econet/binary_sensor.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/homeassistant/components/econet/binary_sensor.py b/homeassistant/components/econet/binary_sensor.py index 91e2c046d2ba8..de62064f1ea26 100644 --- a/homeassistant/components/econet/binary_sensor.py +++ b/homeassistant/components/econet/binary_sensor.py @@ -43,9 +43,6 @@ async def async_setup_entry(hass, entry, async_add_entities): binary_sensors = [] all_equipment = equipment[EquipmentType.WATER_HEATER].copy() all_equipment.extend(equipment[EquipmentType.THERMOSTAT].copy()) - attributes = [] - for sensor in SENSORS.values(): - attributes.append(sensor[ATTR]) for _equip in all_equipment: for name, attribute in attributes: if getattr(_equip, attribute, None) is not None: From 08e1476e8ada0e2a041b57cda3be171da1561cb6 Mon Sep 17 00:00:00 2001 From: William Scanlon Date: Thu, 25 Mar 2021 09:53:24 -0400 Subject: [PATCH 12/12] Update homeassistant/components/econet/binary_sensor.py Co-authored-by: Martin Hjelmare --- homeassistant/components/econet/binary_sensor.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/econet/binary_sensor.py b/homeassistant/components/econet/binary_sensor.py index de62064f1ea26..116b1243ee089 100644 --- a/homeassistant/components/econet/binary_sensor.py +++ b/homeassistant/components/econet/binary_sensor.py @@ -44,9 +44,9 @@ async def async_setup_entry(hass, entry, async_add_entities): all_equipment = equipment[EquipmentType.WATER_HEATER].copy() all_equipment.extend(equipment[EquipmentType.THERMOSTAT].copy()) for _equip in all_equipment: - for name, attribute in attributes: - if getattr(_equip, attribute, None) is not None: - binary_sensors.append(EcoNetBinarySensor(_equip, name)) + for sensor_name, sensor in SENSORS.items(): + if getattr(_equip, sensor[ATTR], None) is not None: + binary_sensors.append(EcoNetBinarySensor(_equip, sensor_name)) async_add_entities(binary_sensors)