diff --git a/.coveragerc b/.coveragerc index e0f797c4d04..b615c4250f8 100644 --- a/.coveragerc +++ b/.coveragerc @@ -67,6 +67,7 @@ omit = homeassistant/components/camera/xiaomi.py homeassistant/components/camera/yi.py homeassistant/components/cast/* + homeassistant/components/climate/coolmaster.py homeassistant/components/climate/ephember.py homeassistant/components/climate/eq3btsmart.py homeassistant/components/climate/flexit.py diff --git a/CODEOWNERS b/CODEOWNERS index a10be84472a..64263598121 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -53,6 +53,7 @@ homeassistant/components/binary_sensor/hikvision.py @mezz64 homeassistant/components/binary_sensor/threshold.py @fabaff homeassistant/components/binary_sensor/uptimerobot.py @ludeeus homeassistant/components/camera/yi.py @bachya +homeassistant/components/climate/coolmaster.py @OnFreund homeassistant/components/climate/ephember.py @ttroy50 homeassistant/components/climate/eq3btsmart.py @rytilahti homeassistant/components/climate/mill.py @danielhiversen diff --git a/homeassistant/components/climate/coolmaster.py b/homeassistant/components/climate/coolmaster.py new file mode 100644 index 00000000000..32c77b93eea --- /dev/null +++ b/homeassistant/components/climate/coolmaster.py @@ -0,0 +1,188 @@ +""" +CoolMasterNet platform that offers control of CoolMasteNet Climate Devices. + +For more details about this platform, please refer to the documentation +https://www.home-assistant.io/components/climate.coolmaster/ +""" + +import logging + +import voluptuous as vol + +from homeassistant.components.climate import ( + PLATFORM_SCHEMA, STATE_AUTO, STATE_COOL, STATE_DRY, STATE_FAN_ONLY, + STATE_HEAT, SUPPORT_FAN_MODE, SUPPORT_ON_OFF, SUPPORT_OPERATION_MODE, + SUPPORT_TARGET_TEMPERATURE, ClimateDevice) +from homeassistant.const import ( + ATTR_TEMPERATURE, CONF_HOST, CONF_PORT, TEMP_CELSIUS, TEMP_FAHRENHEIT) +import homeassistant.helpers.config_validation as cv + +REQUIREMENTS = ['pycoolmasternet==0.0.4'] + +SUPPORT_FLAGS = (SUPPORT_TARGET_TEMPERATURE | SUPPORT_FAN_MODE | + SUPPORT_OPERATION_MODE | SUPPORT_ON_OFF) + +DEFAULT_PORT = 10102 + +AVAILABLE_MODES = [STATE_HEAT, STATE_COOL, STATE_AUTO, STATE_DRY, + STATE_FAN_ONLY] + +CM_TO_HA_STATE = { + 'heat': STATE_HEAT, + 'cool': STATE_COOL, + 'auto': STATE_AUTO, + 'dry': STATE_DRY, + 'fan': STATE_FAN_ONLY, +} + +HA_STATE_TO_CM = {value: key for key, value in CM_TO_HA_STATE.items()} + +FAN_MODES = ['low', 'med', 'high', 'auto'] + +CONF_SUPPORTED_MODES = 'supported_modes' +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_HOST): cv.string, + vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, + vol.Optional(CONF_SUPPORTED_MODES, default=AVAILABLE_MODES): + vol.All(cv.ensure_list, [vol.In(AVAILABLE_MODES)]), +}) + +_LOGGER = logging.getLogger(__name__) + + +def _build_entity(device, supported_modes): + _LOGGER.debug("Found device %s", device.uid) + return CoolmasterClimate(device, supported_modes) + + +def setup_platform(hass, config, add_entities, discovery_info=None): + """Set up the CoolMasterNet climate platform.""" + from pycoolmasternet import CoolMasterNet + + supported_modes = config.get(CONF_SUPPORTED_MODES) + host = config[CONF_HOST] + port = config[CONF_PORT] + cool = CoolMasterNet(host, port=port) + devices = cool.devices() + + all_devices = [_build_entity(device, supported_modes) + for device in devices] + + add_entities(all_devices, True) + + +class CoolmasterClimate(ClimateDevice): + """Representation of a coolmaster climate device.""" + + def __init__(self, device, supported_modes): + """Initialize the climate device.""" + self._device = device + self._uid = device.uid + self._operation_list = supported_modes + self._target_temperature = None + self._current_temperature = None + self._current_fan_mode = None + self._current_operation = None + self._on = None + self._unit = None + + def update(self): + """Pull state from CoolMasterNet.""" + status = self._device.status + self._target_temperature = status['thermostat'] + self._current_temperature = status['temperature'] + self._current_fan_mode = status['fan_speed'] + self._on = status['is_on'] + + device_mode = status['mode'] + self._current_operation = CM_TO_HA_STATE[device_mode] + + if status['unit'] == 'celsius': + self._unit = TEMP_CELSIUS + else: + self._unit = TEMP_FAHRENHEIT + + @property + def unique_id(self): + """Return unique ID for this device.""" + return self._uid + + @property + def supported_features(self): + """Return the list of supported features.""" + return SUPPORT_FLAGS + + @property + def name(self): + """Return the name of the climate device.""" + return self.unique_id + + @property + def temperature_unit(self): + """Return the unit of measurement.""" + return self._unit + + @property + def current_temperature(self): + """Return the current temperature.""" + return self._current_temperature + + @property + def target_temperature(self): + """Return the temperature we are trying to reach.""" + return self._target_temperature + + @property + def current_operation(self): + """Return current operation ie. heat, cool, idle.""" + return self._current_operation + + @property + def operation_list(self): + """Return the list of available operation modes.""" + return self._operation_list + + @property + def is_on(self): + """Return true if the device is on.""" + return self._on + + @property + def current_fan_mode(self): + """Return the fan setting.""" + return self._current_fan_mode + + @property + def fan_list(self): + """Return the list of available fan modes.""" + return FAN_MODES + + def set_temperature(self, **kwargs): + """Set new target temperatures.""" + temp = kwargs.get(ATTR_TEMPERATURE) + if temp is not None: + _LOGGER.debug("Setting temp of %s to %s", self.unique_id, + str(temp)) + self._device.set_thermostat(str(temp)) + + def set_fan_mode(self, fan_mode): + """Set new fan mode.""" + _LOGGER.debug("Setting fan mode of %s to %s", self.unique_id, + fan_mode) + self._device.set_fan_speed(fan_mode) + + def set_operation_mode(self, operation_mode): + """Set new operation mode.""" + _LOGGER.debug("Setting operation mode of %s to %s", self.unique_id, + operation_mode) + self._device.set_mode(HA_STATE_TO_CM[operation_mode]) + + def turn_on(self): + """Turn on.""" + _LOGGER.debug("Turning %s on", self.unique_id) + self._device.turn_on() + + def turn_off(self): + """Turn off.""" + _LOGGER.debug("Turning %s off", self.unique_id) + self._device.turn_off() diff --git a/homeassistant/components/climate/demo.py b/homeassistant/components/climate/demo.py index bc0b9bd52ee..14c22cefbe9 100644 --- a/homeassistant/components/climate/demo.py +++ b/homeassistant/components/climate/demo.py @@ -186,22 +186,22 @@ class DemoClimate(ClimateDevice): self.schedule_update_ha_state() def set_humidity(self, humidity): - """Set new target temperature.""" + """Set new humidity level.""" self._target_humidity = humidity self.schedule_update_ha_state() def set_swing_mode(self, swing_mode): - """Set new target temperature.""" + """Set new swing mode.""" self._current_swing_mode = swing_mode self.schedule_update_ha_state() def set_fan_mode(self, fan_mode): - """Set new target temperature.""" + """Set new fan mode.""" self._current_fan_mode = fan_mode self.schedule_update_ha_state() def set_operation_mode(self, operation_mode): - """Set new target temperature.""" + """Set new operation mode.""" self._current_operation = operation_mode self.schedule_update_ha_state() diff --git a/requirements_all.txt b/requirements_all.txt index 9f2f8ec6366..5911eb938b9 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -957,6 +957,9 @@ pycmus==0.1.1 # homeassistant.components.comfoconnect pycomfoconnect==0.3 +# homeassistant.components.climate.coolmaster +pycoolmasternet==0.0.4 + # homeassistant.components.tts.microsoft pycsspeechtts==1.0.2