Просмотр исходного кода

Merge pull request #17 from nikrolls/custom-updater-support

Custom Updater support
Nik Rolls 6 лет назад
Родитель
Сommit
b5bbaba2f7
9 измененных файлов с 232 добавлено и 204 удалено
  1. 2 1
      .gitignore
  2. 1 1
      LICENSE.md
  3. 52 45
      README.md
  4. 15 0
      custom_components.json
  5. 16 10
      goldair_climate/__init__.py
  6. 136 137
      goldair_climate/climate.py
  7. 2 2
      goldair_climate/light.py
  8. 4 4
      goldair_climate/lock.py
  9. 4 4
      goldair_climate/sensor.py

+ 2 - 1
.gitignore

@@ -1 +1,2 @@
-__pycache__/
+/.idea/
+__pycache__/

+ 1 - 1
LICENSE.md

@@ -4,4 +4,4 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of
 
 
 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
 
 
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ 52 - 45
README.md

@@ -1,7 +1,7 @@
-Home Assistant Goldair WiFi Heater component
-============================================
+Home Assistant Goldair WiFi Climate component
+=============================================
 
 
-The `goldair_heater` component integrates 
+The `goldair_climate` component integrates 
 [Goldair WiFi-enabled heaters](http://www.goldair.co.nz/product-catalogue/heating/wifi-heaters) into Home Assistant, 
 [Goldair WiFi-enabled heaters](http://www.goldair.co.nz/product-catalogue/heating/wifi-heaters) into Home Assistant, 
 enabling control of setting the following parameters via the UI and the following services:
 enabling control of setting the following parameters via the UI and the following services:
 
 
@@ -28,57 +28,79 @@ Current temperature is also displayed.
 Please note, this component has currently only been tested with the Goldair GPPH (inverter) range, however theoretically 
 Please note, this component has currently only been tested with the Goldair GPPH (inverter) range, however theoretically 
 it should also work with GEPH and GPCV devices and any other Goldair heaters based on the Tuya platform.
 it should also work with GEPH and GPCV devices and any other Goldair heaters based on the Tuya platform.
 
 
+Work is in progress to support Goldair WiFi dehumidifiers.
+
 ---
 ---
 
 
-To enable the component, copy the contents of this repository's `component` directory to your
-`<config_dir>/custom_components` directory, then add the following lines to your `configuration.yaml` file:
+Installation
+------------
+The preferred installation method is via [custom_updater](https://github.com/custom-components/custom_updater):
+```yaml
+custom_updater:
+  track:
+    - components
+  component_urls:
+    - https://raw.githubusercontent.com/nikrolls/homeassistant-goldair-climate/master/custom_components.json
+
+```
+Alternatively you can copy the contents of this repository's `goldair_climate` directory to your
+config directory. 
+
+Configuration
+-------------
+Add the following lines to your `configuration.yaml` file:
 
 
 ```yaml
 ```yaml
 # Example configuration.yaml entry
 # Example configuration.yaml entry
-goldair_heater:
+goldair_climate:
   - name: My heater
   - name: My heater
     host: 1.2.3.4
     host: 1.2.3.4
     device_id: <your device id>
     device_id: <your device id>
     local_key: <your local key>
     local_key: <your local key>
+    type: 'heater'
 ```
 ```
 
 
-CONFIGURATION VARIABLES
------------------------
+### Configuration variables
 
 
-### name
+#### name
 &nbsp;&nbsp;&nbsp;&nbsp;*(string) (Required)* Any unique for the device; required because the Tuya API doesn't provide
 &nbsp;&nbsp;&nbsp;&nbsp;*(string) (Required)* Any unique for the device; required because the Tuya API doesn't provide
                                               the one you set in the app.
                                               the one you set in the app.
 
 
-### host
+#### host
 &nbsp;&nbsp;&nbsp;&nbsp;*(string) (Required)* IP or hostname of the device.
 &nbsp;&nbsp;&nbsp;&nbsp;*(string) (Required)* IP or hostname of the device.
 
 
-### device_id
+#### device_id
 &nbsp;&nbsp;&nbsp;&nbsp;*(string) (Required)* Device ID retrieved from the Goldair app logs (see below).
 &nbsp;&nbsp;&nbsp;&nbsp;*(string) (Required)* Device ID retrieved from the Goldair app logs (see below).
 
 
-### local_key
+#### local_key
 &nbsp;&nbsp;&nbsp;&nbsp;*(string) (Required)* Local key retrieved from the Goldair app logs (see below).
 &nbsp;&nbsp;&nbsp;&nbsp;*(string) (Required)* Local key retrieved from the Goldair app logs (see below).
 
 
-### climate
+#### type
+&nbsp;&nbsp;&nbsp;&nbsp;*(string) (Required)* The type of Goldair device. Currently `heater` is the only option; a 
+future update will add support for dehumidifiers, so setting the type now will prevent the component breaking when this
+functionality is released.
+
+#### climate
 &nbsp;&nbsp;&nbsp;&nbsp;*(boolean) (Optional)* Whether to surface this heater as a climate device.
 &nbsp;&nbsp;&nbsp;&nbsp;*(boolean) (Optional)* Whether to surface this heater as a climate device.
 
 
 &nbsp;&nbsp;&nbsp;&nbsp;*Default value: true* 
 &nbsp;&nbsp;&nbsp;&nbsp;*Default value: true* 
 
 
-### sensor
+#### sensor
 &nbsp;&nbsp;&nbsp;&nbsp;*(boolean) (Optional)* Whether to surface this heater's thermometer as a temperature sensor.
 &nbsp;&nbsp;&nbsp;&nbsp;*(boolean) (Optional)* Whether to surface this heater's thermometer as a temperature sensor.
 
 
 &nbsp;&nbsp;&nbsp;&nbsp;*Default value: false* 
 &nbsp;&nbsp;&nbsp;&nbsp;*Default value: false* 
 
 
-### display_light
+#### display_light
 &nbsp;&nbsp;&nbsp;&nbsp;*(boolean) (Optional)* Whether to surface this heater's LED display control as a light.
 &nbsp;&nbsp;&nbsp;&nbsp;*(boolean) (Optional)* Whether to surface this heater's LED display control as a light.
 
 
 &nbsp;&nbsp;&nbsp;&nbsp;*Default value: false* 
 &nbsp;&nbsp;&nbsp;&nbsp;*Default value: false* 
 
 
-### child_lock
+#### child_lock
 &nbsp;&nbsp;&nbsp;&nbsp;*(boolean) (Optional)* Whether to surface this heater's child lock as a lock device.
 &nbsp;&nbsp;&nbsp;&nbsp;*(boolean) (Optional)* Whether to surface this heater's child lock as a lock device.
 
 
 &nbsp;&nbsp;&nbsp;&nbsp;*Default value: false* 
 &nbsp;&nbsp;&nbsp;&nbsp;*Default value: false* 
 
 
-GOTCHAS
+Gotchas
 -------
 -------
 These heaters have individual target temperatures for their Comfort and Eco modes, whereas Home Assistant only supports
 These heaters have individual target temperatures for their Comfort and Eco modes, whereas Home Assistant only supports
 a single target temperature. Therefore, when you're in Comfort mode you will set the Comfort temperature (`5`-`35`), and
 a single target temperature. Therefore, when you're in Comfort mode you will set the Comfort temperature (`5`-`35`), and
@@ -97,42 +119,27 @@ something in HA. This can be confusing because it's the same behaviour as when y
 heater's own control panel and the change is rejected due to being locked, however rest assured that the changes *are* 
 heater's own control panel and the change is rejected due to being locked, however rest assured that the changes *are* 
 taking effect.
 taking effect.
 
 
-FINDING YOUR DEVICE ID AND LOCAL KEY
+Finding your device ID and local key 
 ------------------------------------
 ------------------------------------
+You can find these keys the same way as you would for any Tuya local component. You'll need the Tuya Smart app rather 
+than the Goldair app (the Goldair app is just a re-branded clone of Tuya Smart).
+
+* [Instructions for iOS](https://github.com/codetheweb/tuyapi/blob/master/docs/SETUP.md)
+* [Instructions for Android](https://github.com/codetheweb/tuyapi/blob/cdb4289/docs/SETUP_DEPRECATED.md#capture-https-traffic)
+
+You're looking for the `uuid` (this is the device ID) and the `localKey` values.
 
 
-If you have an Android device that supports Mass Storage mode, you can easily find these properties using the below 
-instructions. If you don't, there are some alternate methods at 
-[codetheweb/tuyapi](https://github.com/codetheweb/tuyapi/blob/master/docs/SETUP.md) (you're looking for the `uuid` and
-`localKey` values).
-
-1. Download the [Goldair app from the Play Store](https://play.google.com/store/apps/details?id=com.goldair.smart).
-2. Follow the instructions in the app to set up the heater. Don't agonise over the name because you'll be giving it a 
-   new one in HA, but do remember it because you'll use this name to find the keys later.
-3. Once this is done and you've verified that you can control the heater from your phone, close the app and plug your 
-   phone into a computer in Mass Storage mode (choose the option to browse files). 
-    * ℹ Alternatively you can use an Android file browser, but bear in mind you will need to search through a large log
-        file
-4. Browse your phone's filesystem to find `/Android/data/com.goldair.smart/cache/1.abj` and open it in a text editor 
-   that can handle large files.
-5. Search for your device in this file by the name you gave it earlier. You're looking for a very long line that 
-   contains not only the device name, but also `uuid` and `localKey` properties. 
-    * ℹ If you've been using the app a while and have added this device more than once, you need to find the last 
-        occurrence of this kind of line for your device in the log file
-6. Copy the value of `uuid` (eg: 1234567890abcdef1234) to `device_id`, and the value of `localKey` 
-   (eg: 1234567890abcdef) to `local_key` in your `configuration.yaml` file.
-
-Repeat for as many heaters as you have to set up.
-
-NEXT STEPS
+Next steps
 ----------
 ----------
 This component needs specs! Once they're written I'm considering submitting it to the HA team for inclusion in standard 
 This component needs specs! Once they're written I'm considering submitting it to the HA team for inclusion in standard 
 installations. Please report any issues and feel free to raise pull requests.
 installations. Please report any issues and feel free to raise pull requests.
 
 
-This was my first Python project, so feel free to correct any conventions or idioms I got wrong.
+I also have a working integration for Goldair WiFi dehumidifiers; it needs to be re-worked to prevent duplicate code
+before releasing it to the wild.
 
 
-ACKNOWLEDGEMENTS
+Acknowledgements
 ----------------
 ----------------
-All I did was write some code. None of this would have been possible without:
+None of this would have been possible without some foundational discovery work to get me started:
 
 
 * [TarxBoy](https://github.com/TarxBoy)'s [investigation using codetheweb/tuyapi](https://github.com/codetheweb/tuyapi/issues/31) to figure out the correlation of the cryptic DPS states 
 * [TarxBoy](https://github.com/TarxBoy)'s [investigation using codetheweb/tuyapi](https://github.com/codetheweb/tuyapi/issues/31) to figure out the correlation of the cryptic DPS states 
 * [sean6541](https://github.com/sean6541)'s [tuya-homeassistant](https://github.com/sean6541/tuya-homeassistant) library giving an example of integrating Tuya devices with Home Assistant
 * [sean6541](https://github.com/sean6541)'s [tuya-homeassistant](https://github.com/sean6541/tuya-homeassistant) library giving an example of integrating Tuya devices with Home Assistant

+ 15 - 0
custom_components.json

@@ -0,0 +1,15 @@
+{
+    "goldair_climate": {
+        "version": "0.0.1",
+        "local_location": "/custom_components/goldair_climate/__init__.py",
+        "remote_location": "https://raw.githubusercontent.com/nikrolls/homeassistant-goldair-climate/master/goldair_climate/__init__.py",
+        "visit_repo": "https://github.com/nikrolls/homeassistant-goldair-climate",
+        "changelog": "https://github.com/nikrolls/homeassistant-goldair-climate/releases/latest",
+        "resources": [
+            "https://raw.githubusercontent.com/nikrolls/homeassistant-goldair-climate/master/goldair_climate/climate.py",
+            "https://raw.githubusercontent.com/nikrolls/homeassistant-goldair-climate/master/goldair_climate/light.py",
+            "https://raw.githubusercontent.com/nikrolls/homeassistant-goldair-climate/master/goldair_climate/lock.py",
+            "https://raw.githubusercontent.com/nikrolls/homeassistant-goldair-climate/master/goldair_climate/sensor.py"
+        ]
+    }
+}

+ 16 - 10
component/goldair_heater.py → goldair_climate/__init__.py

@@ -16,16 +16,19 @@ from homeassistant.const import (CONF_NAME, CONF_HOST, ATTR_TEMPERATURE, TEMP_CE
 from homeassistant.components.climate import ATTR_OPERATION_MODE
 from homeassistant.components.climate import ATTR_OPERATION_MODE
 from homeassistant.helpers.discovery import load_platform
 from homeassistant.helpers.discovery import load_platform
 
 
+VERSION = '0.0.1'
 REQUIREMENTS = ['pytuya==7.0']
 REQUIREMENTS = ['pytuya==7.0']
 
 
 _LOGGER = logging.getLogger(__name__)
 _LOGGER = logging.getLogger(__name__)
 
 
-DOMAIN = 'goldair_heater'
-DATA_GOLDAIR_HEATER = 'data_goldair_heater'
+DOMAIN = 'goldair_climate'
+DATA_GOLDAIR_CLIMATE = 'data_goldair_climate'
 
 
 
 
 CONF_DEVICE_ID = 'device_id'
 CONF_DEVICE_ID = 'device_id'
 CONF_LOCAL_KEY = 'local_key'
 CONF_LOCAL_KEY = 'local_key'
+CONF_TYPE = 'type'
+CONF_TYPE_HEATER = 'heater'
 CONF_CLIMATE = 'climate'
 CONF_CLIMATE = 'climate'
 CONF_SENSOR = 'sensor'
 CONF_SENSOR = 'sensor'
 CONF_CHILD_LOCK = 'child_lock'
 CONF_CHILD_LOCK = 'child_lock'
@@ -82,6 +85,7 @@ PLATFORM_SCHEMA = vol.Schema({
     vol.Required(CONF_HOST): cv.string,
     vol.Required(CONF_HOST): cv.string,
     vol.Required(CONF_DEVICE_ID): cv.string,
     vol.Required(CONF_DEVICE_ID): cv.string,
     vol.Required(CONF_LOCAL_KEY): cv.string,
     vol.Required(CONF_LOCAL_KEY): cv.string,
+    vol.Required(CONF_TYPE): vol.In([CONF_TYPE_HEATER]),
     vol.Optional(CONF_CLIMATE, default=True): cv.boolean,
     vol.Optional(CONF_CLIMATE, default=True): cv.boolean,
     vol.Optional(CONF_SENSOR, default=False): cv.boolean,
     vol.Optional(CONF_SENSOR, default=False): cv.boolean,
     vol.Optional(CONF_DISPLAY_LIGHT, default=False): cv.boolean,
     vol.Optional(CONF_DISPLAY_LIGHT, default=False): cv.boolean,
@@ -106,14 +110,16 @@ def setup(hass, config):
         )
         )
         hass.data[DOMAIN][host] = device
         hass.data[DOMAIN][host] = device
 
 
-        if device_config.get('climate'):
-            load_platform(hass, 'climate', DOMAIN, {'host': host})
-        if device_config.get('sensor'):
-            load_platform(hass, 'sensor', DOMAIN, {'host': host})
-        if device_config.get('display_light'):
-            load_platform(hass, 'light', DOMAIN, {'host': host})
-        if device_config.get('child_lock'):
-            load_platform(hass, 'lock', DOMAIN, {'host': host})
+        if device_config.get(CONF_TYPE) == CONF_TYPE_HEATER:
+            discovery_info = {'host': host, 'type': 'heater'}
+            if device_config.get(CONF_CLIMATE):
+                load_platform(hass, 'climate', DOMAIN, discovery_info, config)
+            if device_config.get(CONF_SENSOR):
+                load_platform(hass, 'sensor', DOMAIN, discovery_info, config)
+            if device_config.get(CONF_DISPLAY_LIGHT):
+                load_platform(hass, 'light', DOMAIN, discovery_info, config)
+            if device_config.get(CONF_CHILD_LOCK):
+                load_platform(hass, 'lock', DOMAIN, discovery_info, config)
 
 
     return True
     return True
 
 

+ 136 - 137
component/climate/goldair_heater.py → goldair_climate/climate.py

@@ -1,137 +1,136 @@
-"""
-Platform to control Goldair WiFi-connected heaters and panels.
-"""
-from homeassistant.components.climate import (
-    ClimateDevice,
-    ATTR_OPERATION_MODE, ATTR_TEMPERATURE,
-    SUPPORT_ON_OFF, SUPPORT_TARGET_TEMPERATURE, SUPPORT_OPERATION_MODE, SUPPORT_SWING_MODE
-)
-from homeassistant.const import STATE_UNAVAILABLE
-import custom_components.goldair_heater as goldair_heater
-
-SUPPORT_FLAGS = SUPPORT_ON_OFF | SUPPORT_TARGET_TEMPERATURE | SUPPORT_OPERATION_MODE | SUPPORT_SWING_MODE
-
-
-def setup_platform(hass, config, add_devices, discovery_info=None):
-    """Set up the Goldair WiFi heater."""
-    device = hass.data[goldair_heater.DOMAIN][discovery_info['host']]
-    add_devices([
-        GoldairHeater(device)
-    ])
-
-
-class GoldairHeater(ClimateDevice):
-    """Representation of a Goldair WiFi heater."""
-
-    def __init__(self, device):
-        """Initialize the heater.
-        Args:
-            name (str): The device's name.
-            device (GoldairHeaterDevice): The device API instance."""
-        self._device = device
-
-        self._support_flags = SUPPORT_FLAGS
-
-    @property
-    def supported_features(self):
-        """Return the list of supported features."""
-        return self._support_flags
-
-    @property
-    def should_poll(self):
-        """Return the polling state."""
-        return True
-
-    @property
-    def name(self):
-        """Return the name of the climate device."""
-        return self._device.name
-
-    @property
-    def state(self):
-        """Return the state of the climate device."""
-        if self._device.is_on is None:
-            return STATE_UNAVAILABLE
-        else:
-            return super().state
-
-    @property
-    def is_on(self):
-        """Return true if the device is on."""
-        return self._device.is_on
-
-    def turn_on(self):
-        """Turn on."""
-        self._device.turn_on()
-
-    def turn_off(self):
-        """Turn off."""
-        self._device.turn_off()
-
-    @property
-    def temperature_unit(self):
-        """Return the unit of measurement."""
-        return self._device.temperature_unit
-
-    @property
-    def target_temperature(self):
-        """Return the temperature we try to reach."""
-        return self._device.target_temperature
-
-    @property
-    def target_temperature_step(self):
-        """Return the supported step of target temperature."""
-        return self._device.target_temperature_step
-
-    @property
-    def min_temp(self):
-        """Return the minimum temperature."""
-        return self._device.min_target_teperature
-
-    @property
-    def max_temp(self):
-        """Return the maximum temperature."""
-        return self._device.max_target_temperature
-
-    def set_temperature(self, **kwargs):
-        """Set new target temperatures."""
-        if kwargs.get(ATTR_TEMPERATURE) is not None:
-            self._device.set_target_temperature(kwargs.get(ATTR_TEMPERATURE))
-        if kwargs.get(ATTR_OPERATION_MODE) is not None:
-            self._device.set_operation_mode(kwargs.get(ATTR_OPERATION_MODE))
-
-    @property
-    def current_temperature(self):
-        """Return the current temperature."""
-        return self._device.current_temperature
-
-    @property
-    def current_operation(self):
-        """Return current operation, ie Comfort, Eco, Anti-freeze."""
-        return self._device.operation_mode
-
-    @property
-    def operation_list(self):
-        """Return the list of available operation modes."""
-        return self._device.operation_mode_list
-
-    def set_operation_mode(self, operation_mode):
-        """Set new operation mode."""
-        self._device.set_operation_mode(operation_mode)
-
-    @property
-    def current_swing_mode(self):
-        """Return the fan setting."""
-        return self._device.power_level
-
-    @property
-    def swing_list(self):
-        """List of available swing modes."""
-        return self._device.power_level_list
-
-    def set_swing_mode(self, swing_mode):
-        """Set new target temperature."""
-        self._device.set_power_level(swing_mode)
-
-    def update(self):
-        self._device.refresh()
+"""
+Platform to control Goldair WiFi-connected heaters and panels.
+"""
+from homeassistant.components.climate import (
+    ClimateDevice, ATTR_OPERATION_MODE, ATTR_TEMPERATURE
+)
+from homeassistant.components.climate.const import (
+    SUPPORT_ON_OFF, SUPPORT_TARGET_TEMPERATURE, SUPPORT_OPERATION_MODE, SUPPORT_SWING_MODE
+)
+from homeassistant.const import STATE_UNAVAILABLE
+import custom_components.goldair_climate as goldair_climate
+
+SUPPORT_FLAGS = SUPPORT_ON_OFF | SUPPORT_TARGET_TEMPERATURE | SUPPORT_OPERATION_MODE | SUPPORT_SWING_MODE
+
+def setup_platform(hass, config, add_devices, discovery_info=None):
+    """Set up the Goldair WiFi heater."""
+    device = hass.data[goldair_climate.DOMAIN][discovery_info['host']]
+    if discovery_info[goldair_climate.CONF_TYPE] == goldair_climate.CONF_TYPE_HEATER:
+        add_devices([GoldairHeater(device)])
+
+
+class GoldairHeater(ClimateDevice):
+    """Representation of a Goldair WiFi heater."""
+
+    def __init__(self, device):
+        """Initialize the heater.
+        Args:
+            name (str): The device's name.
+            device (GoldairHeaterDevice): The device API instance."""
+        self._device = device
+
+        self._support_flags = SUPPORT_FLAGS
+
+    @property
+    def supported_features(self):
+        """Return the list of supported features."""
+        return self._support_flags
+
+    @property
+    def should_poll(self):
+        """Return the polling state."""
+        return True
+
+    @property
+    def name(self):
+        """Return the name of the climate device."""
+        return self._device.name
+
+    @property
+    def state(self):
+        """Return the state of the climate device."""
+        if self._device.is_on is None:
+            return STATE_UNAVAILABLE
+        else:
+            return super().state
+
+    @property
+    def is_on(self):
+        """Return true if the device is on."""
+        return self._device.is_on
+
+    def turn_on(self):
+        """Turn on."""
+        self._device.turn_on()
+
+    def turn_off(self):
+        """Turn off."""
+        self._device.turn_off()
+
+    @property
+    def temperature_unit(self):
+        """Return the unit of measurement."""
+        return self._device.temperature_unit
+
+    @property
+    def target_temperature(self):
+        """Return the temperature we try to reach."""
+        return self._device.target_temperature
+
+    @property
+    def target_temperature_step(self):
+        """Return the supported step of target temperature."""
+        return self._device.target_temperature_step
+
+    @property
+    def min_temp(self):
+        """Return the minimum temperature."""
+        return self._device.min_target_teperature
+
+    @property
+    def max_temp(self):
+        """Return the maximum temperature."""
+        return self._device.max_target_temperature
+
+    def set_temperature(self, **kwargs):
+        """Set new target temperatures."""
+        if kwargs.get(ATTR_TEMPERATURE) is not None:
+            self._device.set_target_temperature(kwargs.get(ATTR_TEMPERATURE))
+        if kwargs.get(ATTR_OPERATION_MODE) is not None:
+            self._device.set_operation_mode(kwargs.get(ATTR_OPERATION_MODE))
+
+    @property
+    def current_temperature(self):
+        """Return the current temperature."""
+        return self._device.current_temperature
+
+    @property
+    def current_operation(self):
+        """Return current operation, ie Comfort, Eco, Anti-freeze."""
+        return self._device.operation_mode
+
+    @property
+    def operation_list(self):
+        """Return the list of available operation modes."""
+        return self._device.operation_mode_list
+
+    def set_operation_mode(self, operation_mode):
+        """Set new operation mode."""
+        self._device.set_operation_mode(operation_mode)
+
+    @property
+    def current_swing_mode(self):
+        """Return the fan setting."""
+        return self._device.power_level
+
+    @property
+    def swing_list(self):
+        """List of available swing modes."""
+        return self._device.power_level_list
+
+    def set_swing_mode(self, swing_mode):
+        """Set new target temperature."""
+        self._device.set_power_level(swing_mode)
+
+    def update(self):
+        self._device.refresh()

+ 2 - 2
component/light/goldair_heater.py → goldair_climate/light.py

@@ -3,11 +3,11 @@ Platform to control the LED display light on Goldair WiFi-connected heaters and
 """
 """
 from homeassistant.components.light import Light
 from homeassistant.components.light import Light
 from homeassistant.const import STATE_UNAVAILABLE
 from homeassistant.const import STATE_UNAVAILABLE
-import custom_components.goldair_heater as goldair_heater
+import custom_components.goldair_climate as goldair_climate
 
 
 
 
 def setup_platform(hass, config, add_devices, discovery_info=None):
 def setup_platform(hass, config, add_devices, discovery_info=None):
-    device = hass.data[goldair_heater.DOMAIN][discovery_info['host']]
+    device = hass.data[goldair_climate.DOMAIN][discovery_info['host']]
     add_devices([
     add_devices([
         GoldairLedDisplayLight(device)
         GoldairLedDisplayLight(device)
     ])
     ])

+ 4 - 4
component/lock/goldair_heater.py → goldair_climate/lock.py

@@ -3,11 +3,11 @@ Platform to control the child lock on Goldair WiFi-connected heaters and panels.
 """
 """
 from homeassistant.components.lock import (STATE_LOCKED, STATE_UNLOCKED, LockDevice)
 from homeassistant.components.lock import (STATE_LOCKED, STATE_UNLOCKED, LockDevice)
 from homeassistant.const import STATE_UNAVAILABLE
 from homeassistant.const import STATE_UNAVAILABLE
-import custom_components.goldair_heater as goldair_heater
+import custom_components.goldair_climate as goldair_climate
 
 
 
 
 def setup_platform(hass, config, add_devices, discovery_info=None):
 def setup_platform(hass, config, add_devices, discovery_info=None):
-    device = hass.data[goldair_heater.DOMAIN][discovery_info['host']]
+    device = hass.data[goldair_climate.DOMAIN][discovery_info['host']]
     add_devices([
     add_devices([
         GoldairChildLock(device)
         GoldairChildLock(device)
     ])
     ])
@@ -17,7 +17,7 @@ class GoldairChildLock(LockDevice):
     """Representation of a Goldair WiFi-connected heater child lock."""
     """Representation of a Goldair WiFi-connected heater child lock."""
 
 
     def __init__(self, device):
     def __init__(self, device):
-        """Initialize the light.
+        """Initialize the lock.
         Args:
         Args:
             device (GoldairHeaterDevice): The device API instance."""
             device (GoldairHeaterDevice): The device API instance."""
         self._device = device
         self._device = device
@@ -29,7 +29,7 @@ class GoldairChildLock(LockDevice):
 
 
     @property
     @property
     def name(self):
     def name(self):
-        """Return the name of the light."""
+        """Return the name of the lock."""
         return self._device.name
         return self._device.name
 
 
     @property
     @property

+ 4 - 4
component/sensor/goldair_heater.py → goldair_climate/sensor.py

@@ -3,11 +3,11 @@ Platform to sense the current temperature at a Goldair WiFi-connected heaters an
 """
 """
 from homeassistant.helpers.entity import Entity
 from homeassistant.helpers.entity import Entity
 from homeassistant.const import STATE_UNAVAILABLE
 from homeassistant.const import STATE_UNAVAILABLE
-import custom_components.goldair_heater as goldair_heater
+import custom_components.goldair_climate as goldair_climate
 
 
 
 
 def setup_platform(hass, config, add_devices, discovery_info=None):
 def setup_platform(hass, config, add_devices, discovery_info=None):
-    device = hass.data[goldair_heater.DOMAIN][discovery_info['host']]
+    device = hass.data[goldair_climate.DOMAIN][discovery_info['host']]
     add_devices([
     add_devices([
         GoldairTemperatureSensor(device)
         GoldairTemperatureSensor(device)
     ])
     ])
@@ -17,7 +17,7 @@ class GoldairTemperatureSensor(Entity):
     """Representation of a Goldair WiFi-connected heater thermometer."""
     """Representation of a Goldair WiFi-connected heater thermometer."""
 
 
     def __init__(self, device):
     def __init__(self, device):
-        """Initialize the light.
+        """Initialize the lock.
         Args:
         Args:
             device (GoldairHeaterDevice): The device API instance."""
             device (GoldairHeaterDevice): The device API instance."""
         self._device = device
         self._device = device
@@ -29,7 +29,7 @@ class GoldairTemperatureSensor(Entity):
 
 
     @property
     @property
     def name(self):
     def name(self):
-        """Return the name of the light."""
+        """Return the name of the sensor."""
         return self._device.name
         return self._device.name
 
 
     @property
     @property