From 0331b409fc9a9223bd67e5625c7fc1a2bdd7a82d Mon Sep 17 00:00:00 2001 From: Robbie Trencheny Date: Mon, 11 Mar 2019 20:42:13 -0700 Subject: [PATCH 1/5] update broadlink climate --- homeassistant/components/climate/broadlink.py | 251 ++++++++++++++++++ homeassistant/components/lametric/notify.py | 2 +- requirements_all.txt | 3 + 3 files changed, 255 insertions(+), 1 deletion(-) create mode 100644 homeassistant/components/climate/broadlink.py diff --git a/homeassistant/components/climate/broadlink.py b/homeassistant/components/climate/broadlink.py new file mode 100644 index 00000000000000..e44ca90300069d --- /dev/null +++ b/homeassistant/components/climate/broadlink.py @@ -0,0 +1,251 @@ +""" +Support for Chinese wifi thermostats (Floureon, Beok, Beca Energy). + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/climate.broadlink/ +""" +import logging + +import voluptuous as vol + +from homeassistant.components.climate import PLATFORM_SCHEMA, ClimateDevice +from homeassistant.components.climate.const import ( + DOMAIN, STATE_AUTO, STATE_HEAT, SUPPORT_AWAY_MODE, SUPPORT_OPERATION_MODE, + SUPPORT_TARGET_TEMPERATURE) +from homeassistant.const import ( + ATTR_ENTITY_ID, ATTR_TEMPERATURE, CONF_FRIENDLY_NAME, CONF_HOST, CONF_MAC, + PRECISION_HALVES, STATE_OFF, TEMP_CELSIUS) +import homeassistant.helpers.config_validation as cv + +REQUIREMENTS = ['BroadlinkWifiThermostat==2.4.1'] + +DEFAULT_NAME = 'broadlink' + +CONF_EXTERNAL_TEMP = 'external_temp' +CONF_AWAY_TEMP = 'away_temp' + +ATTR_LOOP_MODE = 'loop_mode' +ATTR_SEN = 'sen' +ATTR_OSV = 'osv' +ATTR_DIF = 'dif' +ATTR_SVH = 'svh' +ATTR_SVL = 'svl' +ATTR_ADJ = 'adj' +ATTR_FRE = 'freeze' +ATTR_PON = 'pon' + +ATTR_WEEK_START_1 = 'week_start_1' +ATTR_WEEK_STOP_1 = 'week_stop_1' +ATTR_WEEK_START_2 = 'week_start_2' +ATTR_WEEK_STOP_2 = 'week_stop_2' +ATTR_WEEK_START_3 = 'week_start_3' +ATTR_WEEK_STOP_3 = 'week_stop_3' + +ATTR_WEEKEND_START = 'weekend_start' +ATTR_WEEKEND_STOP = 'weekend_stop' +ATTR_AWAY_TEMP = 'away_temp' +ATTR_HOME_TEMP = 'home_temp' + +SERVICE_SET_SCHEDULE = 'broadlink_set_schedule' +SERVICE_SET_ADVANCED_CONF = 'broadlink_set_advanced_conf' + +# Validation of the user's configuration +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_HOST): cv.string, + vol.Required(CONF_MAC): cv.string, + vol.Required(CONF_FRIENDLY_NAME): cv.string, + vol.Optional(CONF_EXTERNAL_TEMP, default=False): cv.boolean, + vol.Optional(CONF_AWAY_TEMP, default=12): vol.Coerce(float), + vol.Optional(ATTR_LOOP_MODE, default=0): vol.Coerce(int) +}) + +SET_SCHEDULE_SCHEMA = vol.Schema({ + vol.Required(ATTR_ENTITY_ID): cv.entity_ids, + vol.Required(ATTR_WEEK_START_1): cv.time, + vol.Required(ATTR_WEEK_STOP_1): cv.time, + vol.Required(ATTR_WEEK_START_2): cv.time, + vol.Required(ATTR_WEEK_STOP_2): cv.time, + vol.Required(ATTR_WEEK_START_3): cv.time, + vol.Required(ATTR_WEEK_STOP_3): cv.time, + vol.Required(ATTR_WEEKEND_START): cv.time, + vol.Required(ATTR_WEEKEND_STOP): cv.time, + vol.Required(ATTR_HOME_TEMP): vol.Coerce(float), + vol.Required(ATTR_AWAY_TEMP): vol.Coerce(float) +}) + +SET_ADVANCED_CONF_SCHEMA = vol.Schema({ + vol.Required(ATTR_ENTITY_ID): cv.entity_ids, + vol.Required(ATTR_LOOP_MODE, default=0): vol.Coerce(int), + vol.Required(ATTR_SEN, default=0): vol.Coerce(int), + vol.Required(ATTR_OSV, default=42): vol.Coerce(int), + vol.Required(ATTR_DIF, default=2): vol.Coerce(int), + vol.Required(ATTR_SVH, default=35): vol.Coerce(int), + vol.Required(ATTR_SVL, default=5): vol.Coerce(int), + vol.Required(ATTR_ADJ, default=0.1): vol.Coerce(float), + vol.Required(ATTR_FRE, default=0): vol.Coerce(int), + vol.Required(ATTR_PON, default=0): vol.Coerce(int) +}) + +_LOGGER = logging.getLogger(__name__) + + +def setup_platform(hass, config, async_add_entities, + discovery_info=None): + """Set up the broadlink thermostat platform.""" + import BroadlinkWifiThermostat + wifi_thermostat = BroadlinkWifiThermostat.\ + Thermostat(config[CONF_MAC], + config[CONF_HOST], + config[CONF_FRIENDLY_NAME], + config[CONF_EXTERNAL_TEMP], + config[CONF_AWAY_TEMP]) + + thermostats = [BroadlinkThermostat(wifi_thermostat)] + + async_add_entities(thermostats, True) + + def set_schedule(service): + """Handle data for the set_schedule service call.""" + entity_id = service.data.get(ATTR_ENTITY_ID) + if entity_id: + target_thermostats = [device for device in thermostats + if device.entity_id in entity_id] + else: + target_thermostats = thermostats + + schedules = dict() + schedules['week_start_1'] = service.data.get(ATTR_WEEK_START_1) + schedules['week_stop_1'] = service.data.get(ATTR_WEEK_STOP_1) + schedules['week_start_2'] = service.data.get(ATTR_WEEK_START_2) + schedules['week_stop_2'] = service.data.get(ATTR_WEEK_STOP_2) + schedules['week_start_3'] = service.data.get(ATTR_WEEK_START_3) + schedules['week_stop_3'] = service.data.get(ATTR_WEEK_STOP_3) + + schedules['weekend_start'] = service.data.get(ATTR_WEEKEND_START) + schedules['weekend_stop'] = service.data.get(ATTR_WEEKEND_STOP) + schedules['away_temp'] = service.data.get(ATTR_AWAY_TEMP) + schedules['home_temp'] = service.data.get(ATTR_HOME_TEMP) + + for thermostat in target_thermostats: + thermostat.set_schedule(schedules) + + hass.services.register(DOMAIN, SERVICE_SET_SCHEDULE, + set_schedule, schema=SET_SCHEDULE_SCHEMA) + + def set_advanced_conf(service): + """Handle data for the set_advanced_conf service call.""" + entity_id = service.data.get(ATTR_ENTITY_ID) + if entity_id: + target_thermostats = [device for device in thermostats + if device.entity_id in entity_id] + else: + target_thermostats = thermostats + + advance_conf = dict() + advance_conf["loop_mode"] = service.data.get(ATTR_LOOP_MODE) + advance_conf['sen'] = service.data.get(ATTR_SEN) + advance_conf['osv'] = service.data.get(ATTR_OSV) + advance_conf['dif'] = service.data.get(ATTR_DIF) + advance_conf['svh'] = service.data.get(ATTR_SVH) + advance_conf['svl'] = service.data.get(ATTR_SVL) + advance_conf['adj'] = service.data.get(ATTR_ADJ) + advance_conf['fre'] = service.data.get(ATTR_FRE) + advance_conf['pon'] = service.data.get(ATTR_PON) + target_thermostats.set_advanced_config(advance_conf) + + hass.services.register(DOMAIN, SERVICE_SET_ADVANCED_CONF, + set_advanced_conf, schema=SET_SCHEDULE_SCHEMA) + + +class BroadlinkThermostat(ClimateDevice): + """Representation of a Broadlink Thermostat device.""" + + def __init__(self, device): + """Initialize the climate device.""" + self._device = device + device.set_time() + + @property + def state(self): + """Return climate state.""" + return self._device.state + + @property + def supported_features(self): + """Return the list of supported features.""" + return SUPPORT_TARGET_TEMPERATURE | SUPPORT_OPERATION_MODE \ + | SUPPORT_AWAY_MODE + + @property + def name(self): + """Return the name of the thermostat.""" + return self._device.name + + @property + def temperature_unit(self): + """Return the unit of measurement.""" + return TEMP_CELSIUS + + @property + def current_temperature(self): + """Return the sensor temperature.""" + return self._device.current_temp + + @property + def target_temperature(self): + """Return the temperature we try to reach.""" + return self._device.target_temperature + + @property + def current_operation(self): + """Return current operation.""" + return self._device.current_operation + + @property + def operation_list(self): + """List of available operation modes.""" + return [STATE_AUTO, STATE_HEAT, STATE_OFF] + + @property + def is_away_mode_on(self): + """Return if away mode is on.""" + return self._device.away + + @property + def is_on(self): + """Return true if the device is on.""" + return not self._device.current_operation == STATE_OFF + + @property + def precision(self): + """Return the precision of the system.""" + return PRECISION_HALVES + + def set_temperature(self, **kwargs): + """Set new target temperature.""" + if kwargs.get(ATTR_TEMPERATURE) is not None: + self._device.set_temperature(kwargs.get(ATTR_TEMPERATURE)) + + def set_operation_mode(self, operation_mode): + """Set operation mode.""" + self._device.set_operation_mode(operation_mode) + + def set_schedule(self, schedules): + """Set automatic schedule.""" + self._device.set_schedule(schedules) + + def set_advanced_config(self, advanced_conf): + """Set advanced configuration.""" + self._device.set_advanced_config(self, advanced_conf) + + def turn_away_mode_on(self): + """Turn away mode on.""" + self._device.set_away(True) + + def turn_away_mode_off(self): + """Turn away mode off.""" + self._device.set_away(False) + + def update(self): + """Update component data.""" + self._device.read_status() diff --git a/homeassistant/components/lametric/notify.py b/homeassistant/components/lametric/notify.py index e5e6a5bd522960..9903676d9f965e 100644 --- a/homeassistant/components/lametric/notify.py +++ b/homeassistant/components/lametric/notify.py @@ -24,7 +24,7 @@ DEPENDENCIES = ['lametric'] PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - vol.Optional(CONF_ICON, default='i555'): cv.string, + vol.Optional(CONF_ICON, default='a7956'): cv.string, vol.Optional(CONF_LIFETIME, default=10): cv.positive_int, vol.Optional(CONF_CYCLES, default=1): cv.positive_int, vol.Optional(CONF_PRIORITY, default='warning'): diff --git a/requirements_all.txt b/requirements_all.txt index 08b4f1bb5df0b0..12b54c0bba7a5d 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -32,6 +32,9 @@ Adafruit-SHT31==1.0.2 # homeassistant.components.bbb_gpio # Adafruit_BBIO==1.0.0 +# homeassistant.components.climate.broadlink +BroadlinkWifiThermostat==2.4.1 + # homeassistant.components.homekit HAP-python==2.4.2 From 8ffa8e66a918bc21d1252a6d55162f5cf04a26fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20TALVARD?= Date: Tue, 12 Mar 2019 08:37:27 +0100 Subject: [PATCH 2/5] Update notify.py --- homeassistant/components/lametric/notify.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/lametric/notify.py b/homeassistant/components/lametric/notify.py index 9903676d9f965e..e5e6a5bd522960 100644 --- a/homeassistant/components/lametric/notify.py +++ b/homeassistant/components/lametric/notify.py @@ -24,7 +24,7 @@ DEPENDENCIES = ['lametric'] PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - vol.Optional(CONF_ICON, default='a7956'): cv.string, + vol.Optional(CONF_ICON, default='i555'): cv.string, vol.Optional(CONF_LIFETIME, default=10): cv.positive_int, vol.Optional(CONF_CYCLES, default=1): cv.positive_int, vol.Optional(CONF_PRIORITY, default='warning'): From cd8eaa238d19c5343bc0d417a0f5c1b8528a9559 Mon Sep 17 00:00:00 2001 From: clementtal Date: Tue, 12 Mar 2019 15:17:17 +0100 Subject: [PATCH 3/5] refactor to braodlink component --- .coveragerc | 1 + homeassistant/components/broadlink/__init__.py | 1 + .../components/{climate/broadlink.py => broadlink/climate.py} | 3 +-- requirements_all.txt | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 homeassistant/components/broadlink/__init__.py rename homeassistant/components/{climate/broadlink.py => broadlink/climate.py} (99%) diff --git a/.coveragerc b/.coveragerc index b25d8e1f54b37e..57a58cfc58bdad 100644 --- a/.coveragerc +++ b/.coveragerc @@ -50,6 +50,7 @@ omit = homeassistant/components/blink/* homeassistant/components/bloomsky/* homeassistant/components/bmw_connected_drive/* + homeassistant/components/broadlink/* homeassistant/components/browser/* homeassistant/components/calendar/caldav.py homeassistant/components/calendar/todoist.py diff --git a/homeassistant/components/broadlink/__init__.py b/homeassistant/components/broadlink/__init__.py new file mode 100644 index 00000000000000..6b6c725b50c560 --- /dev/null +++ b/homeassistant/components/broadlink/__init__.py @@ -0,0 +1 @@ +"""Component to embed broadlink.""" diff --git a/homeassistant/components/climate/broadlink.py b/homeassistant/components/broadlink/climate.py similarity index 99% rename from homeassistant/components/climate/broadlink.py rename to homeassistant/components/broadlink/climate.py index e44ca90300069d..d43786496f31fb 100644 --- a/homeassistant/components/climate/broadlink.py +++ b/homeassistant/components/broadlink/climate.py @@ -17,9 +17,8 @@ PRECISION_HALVES, STATE_OFF, TEMP_CELSIUS) import homeassistant.helpers.config_validation as cv -REQUIREMENTS = ['BroadlinkWifiThermostat==2.4.1'] -DEFAULT_NAME = 'broadlink' +REQUIREMENTS = ['BroadlinkWifiThermostat==2.4.1'] CONF_EXTERNAL_TEMP = 'external_temp' CONF_AWAY_TEMP = 'away_temp' diff --git a/requirements_all.txt b/requirements_all.txt index 12b54c0bba7a5d..6987a2d7ab7bcd 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -32,7 +32,7 @@ Adafruit-SHT31==1.0.2 # homeassistant.components.bbb_gpio # Adafruit_BBIO==1.0.0 -# homeassistant.components.climate.broadlink +# homeassistant.components.broadlink.broadlink BroadlinkWifiThermostat==2.4.1 # homeassistant.components.homekit From 2599ae54c334eaf52162737b2f84b36ce43157a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20TALVARD?= Date: Thu, 16 May 2019 09:48:05 +0200 Subject: [PATCH 4/5] Update homeassistant/components/broadlink/climate.py Co-Authored-By: Francesco Antognazza --- homeassistant/components/broadlink/climate.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/broadlink/climate.py b/homeassistant/components/broadlink/climate.py index d43786496f31fb..442d500c61649d 100644 --- a/homeassistant/components/broadlink/climate.py +++ b/homeassistant/components/broadlink/climate.py @@ -150,7 +150,8 @@ def set_advanced_conf(service): advance_conf['adj'] = service.data.get(ATTR_ADJ) advance_conf['fre'] = service.data.get(ATTR_FRE) advance_conf['pon'] = service.data.get(ATTR_PON) - target_thermostats.set_advanced_config(advance_conf) + for thermostat in target_thermostats: + thermostat.set_advanced_conf(advance_conf) hass.services.register(DOMAIN, SERVICE_SET_ADVANCED_CONF, set_advanced_conf, schema=SET_SCHEDULE_SCHEMA) From 0a5efe114a982a4faac9daa0855ce9d6e2cf6404 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20TALVARD?= Date: Thu, 16 May 2019 09:48:18 +0200 Subject: [PATCH 5/5] Update homeassistant/components/broadlink/climate.py Co-Authored-By: Francesco Antognazza --- homeassistant/components/broadlink/climate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/broadlink/climate.py b/homeassistant/components/broadlink/climate.py index 442d500c61649d..ca58696ef59eeb 100644 --- a/homeassistant/components/broadlink/climate.py +++ b/homeassistant/components/broadlink/climate.py @@ -154,7 +154,7 @@ def set_advanced_conf(service): thermostat.set_advanced_conf(advance_conf) hass.services.register(DOMAIN, SERVICE_SET_ADVANCED_CONF, - set_advanced_conf, schema=SET_SCHEDULE_SCHEMA) + set_advanced_conf, schema=SET_ADVANCED_CONF_SCHEMA) class BroadlinkThermostat(ClimateDevice):