Bladeren bron

WIP: Surface error state and fix UI strings

Fixes #25 by adding an attribute to the Dehumidifier component allowing
you to set up a template sensor based on that attribute's value.
Nik Rolls 6 jaren geleden
bovenliggende
commit
6560ab3e32

+ 5 - 3
README.md

@@ -2,7 +2,7 @@ Home Assistant Goldair WiFi Climate component
 =============================================
 =============================================
 
 
 The `goldair_climate` component integrates 
 The `goldair_climate` component integrates 
-[Goldair WiFi-enabled heaters](http://www.goldair.co.nz/product-catalogue/heating/wifi-heaters), WiFi-enabled [dehumidifiers](http://www.goldair.co.nz/product-catalogue/heating/dehumidifiers), and WiFi-enabled fans](http://www.goldair.co.nz/product-catalogue/cooling/pedestal-fans/40cm-dc-quiet-fan-with-wifi-and-remote-gcpf315) into Home Assistant, enabling control of setting the following parameters via the UI and the following services:
+[Goldair WiFi-enabled heaters](http://www.goldair.co.nz/product-catalogue/heating/wifi-heaters), WiFi-enabled [dehumidifiers](http://www.goldair.co.nz/product-catalogue/heating/dehumidifiers), and [WiFi-enabled fans](http://www.goldair.co.nz/product-catalogue/cooling/pedestal-fans/40cm-dc-quiet-fan-with-wifi-and-remote-gcpf315) into Home Assistant, enabling control of setting the following parameters via the UI and the following services:
 
 
 **Heaters**
 **Heaters**
 * **power** (on/off)
 * **power** (on/off)
@@ -17,7 +17,7 @@ Current temperature is also displayed.
 * **mode** (Normal, Low, High, Dry clothes, Air clean)
 * **mode** (Normal, Low, High, Dry clothes, Air clean)
 * **target humidity** (`30`-`80`%)
 * **target humidity** (`30`-`80`%)
 
 
-Current temperature is displayed, and current humidity is available as a property.
+Current temperature is displayed, and current humidity is available as a property. The "tank full" state is available via the **error** attribute, and if you want to you can easily surface this to a top-level entity using a [template sensor](https://www.home-assistant.io/integrations/template/).
 
 
 **Fans**
 **Fans**
 * **power** (on/off)
 * **power** (on/off)
@@ -54,7 +54,9 @@ Alternatively you can copy the contents of this repository's `custom_components`
 
 
 Configuration
 Configuration
 -------------
 -------------
-Add the following lines to your `configuration.yaml` file:
+You can easily configure your devices using the Integrations UI at `Home Assistant > Configuration > Integrations > +`. This is the preferred method as things will be unlikely to break as this integration is upgraded. You will need to provide your device's IP address, device ID and local key; the last two can be found using [the instructions below](#finding-your-device-id-and-local-key).
+
+If you would rather configure using yaml, add the following lines to your `configuration.yaml` file (but bear in mind that if the configuration options change your configuration may break until you update it to match the changes):
 
 
 ```yaml
 ```yaml
 # Example configuration.yaml entry
 # Example configuration.yaml entry

+ 1 - 0
custom_components/goldair_climate/.translations

@@ -0,0 +1 @@
+translations

+ 13 - 13
custom_components/goldair_climate/__init__.py

@@ -27,19 +27,19 @@ DOMAIN = 'goldair_climate'
 DATA_GOLDAIR_CLIMATE = 'data_goldair_climate'
 DATA_GOLDAIR_CLIMATE = 'data_goldair_climate'
 
 
 INDIVIDUAL_CONFIG_SCHEMA_TEMPLATE = [
 INDIVIDUAL_CONFIG_SCHEMA_TEMPLATE = [
-    {'key': CONF_NAME, 'type': cv.string, 'required': True},
-    {'key': CONF_HOST, 'type': cv.string, 'required': True},
-    {'key': CONF_DEVICE_ID, 'type': cv.string, 'required': True, 'fixed': True},
-    {'key': CONF_LOCAL_KEY, 'type': cv.string, 'required': True},
+    {'key': CONF_NAME, 'type': str, 'required': True},
+    {'key': CONF_HOST, 'type': str, 'required': True},
+    {'key': CONF_DEVICE_ID, 'type': str, 'required': True, 'fixed': True},
+    {'key': CONF_LOCAL_KEY, 'type': str, 'required': True},
     {
     {
         'key': CONF_TYPE,
         'key': CONF_TYPE,
         'type': vol.In([CONF_TYPE_HEATER, CONF_TYPE_DEHUMIDIFIER, CONF_TYPE_FAN]),
         'type': vol.In([CONF_TYPE_HEATER, CONF_TYPE_DEHUMIDIFIER, CONF_TYPE_FAN]),
         'required': True,
         'required': True,
         'fixed': True
         'fixed': True
     },
     },
-    {'key': CONF_CLIMATE, 'type': cv.boolean, 'required': False, 'default': True},
-    {'key': CONF_DISPLAY_LIGHT, 'type': cv.boolean, 'required': False, 'default': False},
-    {'key': CONF_CHILD_LOCK, 'type': cv.boolean, 'required': False, 'default': False}
+    {'key': CONF_CLIMATE, 'type': bool, 'required': False, 'default': True},
+    {'key': CONF_DISPLAY_LIGHT, 'type': bool, 'required': False, 'default': False},
+    {'key': CONF_CHILD_LOCK, 'type': bool, 'required': False, 'default': False}
 ]
 ]
 
 
 
 
@@ -50,14 +50,14 @@ def individual_config_schema(defaults={}, exclude_fixed=False):
         if exclude_fixed and prop.get('fixed'):
         if exclude_fixed and prop.get('fixed'):
             continue
             continue
 
 
+        options = {}
+
         default = defaults.get(prop['key'], prop.get('default'))
         default = defaults.get(prop['key'], prop.get('default'))
         if default is not None:
         if default is not None:
-            key = vol.Required(prop['key'], default=default) if prop['required'] else vol.Optional(prop['key'],
-                                                                                                   default=default)
-            output[key] = prop['type']
-        else:
-            key = vol.Required(prop['key']) if prop['required'] else vol.Optional(prop['key'])
-            output[key] = prop['type']
+            options['default'] = default
+
+        key = vol.Required(prop['key'], **options) if prop['required'] else vol.Optional(prop['key'], **options)
+        output[key] = prop['type']
 
 
     return output
     return output
 
 

+ 3 - 15
custom_components/goldair_climate/config_flow.py

@@ -8,18 +8,6 @@ from . import (DOMAIN, individual_config_schema)
 from .const import (CONF_DEVICE_ID, CONF_TYPE)
 from .const import (CONF_DEVICE_ID, CONF_TYPE)
 
 
 
 
-def cv_schema_to_config_schema(schema):
-    config_schema = {}
-    for key, value in schema.items():
-        if value == cv.string:
-            config_schema[key] = str
-        elif value == cv.boolean:
-            config_schema[key] = bool
-        else:
-            config_schema[key] = value
-    return vol.Schema(config_schema)
-
-
 class ConfigFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
 class ConfigFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
     VERSION = 1
     VERSION = 1
     CONNECTION_CLASS = config_entries.CONN_CLASS_LOCAL_POLL
     CONNECTION_CLASS = config_entries.CONN_CLASS_LOCAL_POLL
@@ -34,7 +22,7 @@ class ConfigFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
 
 
         return self.async_show_form(
         return self.async_show_form(
             step_id='user',
             step_id='user',
-            data_schema=cv_schema_to_config_schema(individual_config_schema())
+            data_schema=vol.Schema(individual_config_schema())
         )
         )
 
 
     @staticmethod
     @staticmethod
@@ -57,6 +45,6 @@ class OptionsFlowHandler(config_entries.OptionsFlow):
 
 
         config = {**self.config_entry.data, **self.config_entry.options}
         config = {**self.config_entry.data, **self.config_entry.options}
         return self.async_show_form(
         return self.async_show_form(
-            step_id='init',
-            data_schema=cv_schema_to_config_schema(individual_config_schema(defaults=config, exclude_fixed=True))
+            step_id='user',
+            data_schema=vol.Schema(individual_config_schema(defaults=config, exclude_fixed=True))
         )
         )

+ 11 - 13
custom_components/goldair_climate/dehumidifier/climate.py

@@ -1,18 +1,16 @@
 """
 """
 Goldair WiFi Dehumidifier device.
 Goldair WiFi Dehumidifier device.
 """
 """
-from homeassistant.const import (
-    ATTR_TEMPERATURE, TEMP_CELSIUS, STATE_UNAVAILABLE
-)
+from homeassistant.const import (ATTR_TEMPERATURE, STATE_UNAVAILABLE)
 from homeassistant.components.climate import ClimateDevice
 from homeassistant.components.climate import ClimateDevice
 from homeassistant.components.climate.const import (
 from homeassistant.components.climate.const import (
     ATTR_FAN_MODE, ATTR_HUMIDITY, ATTR_HVAC_MODE, ATTR_PRESET_MODE, FAN_LOW, FAN_HIGH, SUPPORT_TARGET_HUMIDITY,
     ATTR_FAN_MODE, ATTR_HUMIDITY, ATTR_HVAC_MODE, ATTR_PRESET_MODE, FAN_LOW, FAN_HIGH, SUPPORT_TARGET_HUMIDITY,
     SUPPORT_PRESET_MODE, SUPPORT_FAN_MODE
     SUPPORT_PRESET_MODE, SUPPORT_FAN_MODE
 )
 )
 from .const import (
 from .const import (
-    ATTR_TARGET_HUMIDITY, ATTR_AIR_CLEAN_ON, ATTR_FAULT, PRESET_NORMAL, PRESET_LOW, PRESET_HIGH, PRESET_DRY_CLOTHES,
-    PRESET_AIR_CLEAN, FAULT_NONE, PROPERTY_TO_DPS_ID, HVAC_MODE_TO_DPS_MODE, PRESET_MODE_TO_DPS_MODE,
-    FAN_MODE_TO_DPS_MODE, FAULT_CODE_TO_DPS_CODE
+    ATTR_TARGET_HUMIDITY, ATTR_AIR_CLEAN_ON, ATTR_ERROR, PRESET_NORMAL, PRESET_LOW, PRESET_HIGH, PRESET_DRY_CLOTHES,
+    PRESET_AIR_CLEAN, PROPERTY_TO_DPS_ID, HVAC_MODE_TO_DPS_MODE, PRESET_MODE_TO_DPS_MODE, FAN_MODE_TO_DPS_MODE,
+    ERROR_CODE_TO_DPS_CODE
 )
 )
 from ..device import GoldairTuyaDevice
 from ..device import GoldairTuyaDevice
 
 
@@ -193,13 +191,13 @@ class GoldairDehumidifier(ClimateDevice):
         await self._device.async_set_property(PROPERTY_TO_DPS_ID[ATTR_FAN_MODE], dps_mode)
         await self._device.async_set_property(PROPERTY_TO_DPS_ID[ATTR_FAN_MODE], dps_mode)
 
 
     @property
     @property
-    def fault(self):
-        """Get the current fault status."""
-        fault = self._device.get_property(PROPERTY_TO_DPS_ID[ATTR_FAULT])
-        if fault is None or fault == FAULT_NONE:
-            return None
-        else:
-            return GoldairTuyaDevice.get_key_for_value(FAULT_CODE_TO_DPS_CODE, fault)
+    def device_state_attributes(self):
+        """Get additional attributes that HA doesn't naturally support."""
+        error = self._device.get_property(PROPERTY_TO_DPS_ID[ATTR_ERROR])
+        if error:
+            error = GoldairTuyaDevice.get_key_for_value(ERROR_CODE_TO_DPS_CODE, error, error)
+
+        return {ATTR_ERROR: error or None}
 
 
     async def async_update(self):
     async def async_update(self):
         await self._device.async_refresh()
         await self._device.async_refresh()

+ 7 - 7
custom_components/goldair_climate/dehumidifier/const.py

@@ -6,7 +6,7 @@ from homeassistant.components.climate.const import (
 ATTR_TARGET_HUMIDITY = 'target_humidity'
 ATTR_TARGET_HUMIDITY = 'target_humidity'
 ATTR_AIR_CLEAN_ON = 'air_clean_on'
 ATTR_AIR_CLEAN_ON = 'air_clean_on'
 ATTR_CHILD_LOCK = 'child_lock'
 ATTR_CHILD_LOCK = 'child_lock'
-ATTR_FAULT = 'fault'
+ATTR_ERROR = 'error'
 ATTR_DISPLAY_ON = 'display_on'
 ATTR_DISPLAY_ON = 'display_on'
 
 
 PRESET_NORMAL = 'Normal'
 PRESET_NORMAL = 'Normal'
@@ -15,8 +15,8 @@ PRESET_HIGH = 'High'
 PRESET_DRY_CLOTHES = 'Dry clothes'
 PRESET_DRY_CLOTHES = 'Dry clothes'
 PRESET_AIR_CLEAN = 'Air clean'
 PRESET_AIR_CLEAN = 'Air clean'
 
 
-FAULT_NONE = 'No fault'
-FAULT_TANK = 'Tank full or missing'
+ERROR_NONE = 'No error'
+ERROR_TANK = 'Tank full or missing'
 
 
 PROPERTY_TO_DPS_ID = {
 PROPERTY_TO_DPS_ID = {
     ATTR_HVAC_MODE: '1',
     ATTR_HVAC_MODE: '1',
@@ -25,7 +25,7 @@ PROPERTY_TO_DPS_ID = {
     ATTR_AIR_CLEAN_ON: '5',
     ATTR_AIR_CLEAN_ON: '5',
     ATTR_FAN_MODE: '6',
     ATTR_FAN_MODE: '6',
     ATTR_CHILD_LOCK: '7',
     ATTR_CHILD_LOCK: '7',
-    ATTR_FAULT: '11',
+    ATTR_ERROR: '11',
     ATTR_DISPLAY_ON: '102',
     ATTR_DISPLAY_ON: '102',
     ATTR_TEMPERATURE: '103',
     ATTR_TEMPERATURE: '103',
     ATTR_HUMIDITY: '104'
     ATTR_HUMIDITY: '104'
@@ -45,7 +45,7 @@ FAN_MODE_TO_DPS_MODE = {
     FAN_LOW: '1',
     FAN_LOW: '1',
     FAN_HIGH: '3'
     FAN_HIGH: '3'
 }
 }
-FAULT_CODE_TO_DPS_CODE = {
-    FAULT_NONE: 0,
-    FAULT_TANK: 8
+ERROR_CODE_TO_DPS_CODE = {
+    ERROR_NONE: 0,
+    ERROR_TANK: 8
 }
 }

+ 1 - 1
custom_components/goldair_climate/dehumidifier/light.py

@@ -53,7 +53,7 @@ class GoldairDehumidifierLedDisplayLight(Light):
         dps_display_on = self._device.get_property(PROPERTY_TO_DPS_ID[ATTR_DISPLAY_ON])
         dps_display_on = self._device.get_property(PROPERTY_TO_DPS_ID[ATTR_DISPLAY_ON])
 
 
         if dps_hvac_mode != HVAC_MODE_TO_DPS_MODE[HVAC_MODE_OFF]:
         if dps_hvac_mode != HVAC_MODE_TO_DPS_MODE[HVAC_MODE_OFF]:
-            await self.turn_on() if not dps_display_on else await self.turn_off()
+            await (self.turn_on() if not dps_display_on else self.turn_off())
 
 
     async def async_update(self):
     async def async_update(self):
         await self._device.async_refresh()
         await self._device.async_refresh()

+ 1 - 3
custom_components/goldair_climate/dehumidifier/lock.py

@@ -4,9 +4,7 @@ Platform to control the child lock on Goldair WiFi-connected dehumidifiers.
 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
 from ..device import GoldairTuyaDevice
 from ..device import GoldairTuyaDevice
-from .const import (
-    ATTR_CHILD_LOCK, PROPERTY_TO_DPS_ID
-)
+from .const import (ATTR_CHILD_LOCK, PROPERTY_TO_DPS_ID)
 
 
 
 
 class GoldairDehumidifierChildLock(LockDevice):
 class GoldairDehumidifierChildLock(LockDevice):

+ 2 - 2
custom_components/goldair_climate/device.py

@@ -193,7 +193,7 @@ class GoldairTuyaDevice(object):
         self._api.set_version(new_version)
         self._api.set_version(new_version)
 
 
     @staticmethod
     @staticmethod
-    def get_key_for_value(obj, value):
+    def get_key_for_value(obj, value, fallback=None):
         keys = list(obj.keys())
         keys = list(obj.keys())
         values = list(obj.values())
         values = list(obj.values())
-        return keys[values.index(value)]
+        return keys[values.index(value)] or fallback

+ 1 - 1
custom_components/goldair_climate/fan/light.py

@@ -53,7 +53,7 @@ class GoldairFanLedDisplayLight(Light):
         dps_display_on = self._device.get_property(PROPERTY_TO_DPS_ID[ATTR_DISPLAY_ON])
         dps_display_on = self._device.get_property(PROPERTY_TO_DPS_ID[ATTR_DISPLAY_ON])
 
 
         if dps_hvac_mode != HVAC_MODE_TO_DPS_MODE[HVAC_MODE_OFF]:
         if dps_hvac_mode != HVAC_MODE_TO_DPS_MODE[HVAC_MODE_OFF]:
-            await self.async_turn_on() if not dps_display_on else await self.async_turn_off()
+            await (self.async_turn_on() if not dps_display_on else self.async_turn_off())
 
 
     async def async_update(self):
     async def async_update(self):
         await self._device.async_refresh()
         await self._device.async_refresh()

+ 9 - 4
custom_components/goldair_climate/heater/climate.py

@@ -1,9 +1,7 @@
 """
 """
 Goldair WiFi Heater device.
 Goldair WiFi Heater device.
 """
 """
-from homeassistant.const import (
-    ATTR_TEMPERATURE, TEMP_CELSIUS, STATE_UNAVAILABLE
-)
+from homeassistant.const import (ATTR_TEMPERATURE, STATE_UNAVAILABLE)
 from homeassistant.components.climate import ClimateDevice
 from homeassistant.components.climate import ClimateDevice
 from homeassistant.components.climate.const import (
 from homeassistant.components.climate.const import (
     ATTR_HVAC_MODE, ATTR_PRESET_MODE,
     ATTR_HVAC_MODE, ATTR_PRESET_MODE,
@@ -11,7 +9,7 @@ from homeassistant.components.climate.const import (
 )
 )
 from ..device import GoldairTuyaDevice
 from ..device import GoldairTuyaDevice
 from .const import (
 from .const import (
-    ATTR_TARGET_TEMPERATURE, ATTR_POWER_MODE_AUTO, ATTR_POWER_MODE_USER, ATTR_POWER_LEVEL, ATTR_POWER_MODE,
+    ATTR_TARGET_TEMPERATURE, ATTR_ERROR, ATTR_POWER_MODE_AUTO, ATTR_POWER_MODE_USER, ATTR_POWER_LEVEL, ATTR_POWER_MODE,
     ATTR_ECO_TARGET_TEMPERATURE, STATE_COMFORT, STATE_ECO, STATE_ANTI_FREEZE, PROPERTY_TO_DPS_ID, HVAC_MODE_TO_DPS_MODE,
     ATTR_ECO_TARGET_TEMPERATURE, STATE_COMFORT, STATE_ECO, STATE_ANTI_FREEZE, PROPERTY_TO_DPS_ID, HVAC_MODE_TO_DPS_MODE,
     PRESET_MODE_TO_DPS_MODE, POWER_LEVEL_TO_DPS_LEVEL
     PRESET_MODE_TO_DPS_MODE, POWER_LEVEL_TO_DPS_LEVEL
 )
 )
@@ -188,5 +186,12 @@ class GoldairHeater(ClimateDevice):
         dps_level = POWER_LEVEL_TO_DPS_LEVEL[new_level]
         dps_level = POWER_LEVEL_TO_DPS_LEVEL[new_level]
         await self._device.async_set_property(PROPERTY_TO_DPS_ID[ATTR_POWER_LEVEL], dps_level)
         await self._device.async_set_property(PROPERTY_TO_DPS_ID[ATTR_POWER_LEVEL], dps_level)
 
 
+    @property
+    def device_state_attributes(self):
+        """Get additional attributes that HA doesn't naturally support."""
+        error = self._device.get_property(PROPERTY_TO_DPS_ID[ATTR_ERROR])
+
+        return {ATTR_ERROR: error or None}
+
     async def async_update(self):
     async def async_update(self):
         await self._device.async_refresh()
         await self._device.async_refresh()

+ 2 - 2
custom_components/goldair_climate/heater/const.py

@@ -5,7 +5,7 @@ from homeassistant.components.climate.const import (
 
 
 ATTR_TARGET_TEMPERATURE = 'target_temperature'
 ATTR_TARGET_TEMPERATURE = 'target_temperature'
 ATTR_CHILD_LOCK = 'child_lock'
 ATTR_CHILD_LOCK = 'child_lock'
-ATTR_FAULT = 'fault'
+ATTR_ERROR = 'error'
 ATTR_POWER_MODE_AUTO = 'auto'
 ATTR_POWER_MODE_AUTO = 'auto'
 ATTR_POWER_MODE_USER = 'user'
 ATTR_POWER_MODE_USER = 'user'
 ATTR_POWER_LEVEL = 'power_level'
 ATTR_POWER_LEVEL = 'power_level'
@@ -23,7 +23,7 @@ PROPERTY_TO_DPS_ID = {
     ATTR_TEMPERATURE: '3',
     ATTR_TEMPERATURE: '3',
     ATTR_PRESET_MODE: '4',
     ATTR_PRESET_MODE: '4',
     ATTR_CHILD_LOCK: '6',
     ATTR_CHILD_LOCK: '6',
-    ATTR_FAULT: '12',
+    ATTR_ERROR: '12',
     ATTR_POWER_LEVEL: '101',
     ATTR_POWER_LEVEL: '101',
     ATTR_DISPLAY_ON: '104',
     ATTR_DISPLAY_ON: '104',
     ATTR_POWER_MODE: '105',
     ATTR_POWER_MODE: '105',

+ 1 - 1
custom_components/goldair_climate/heater/light.py

@@ -53,7 +53,7 @@ class GoldairHeaterLedDisplayLight(Light):
         dps_display_on = self._device.get_property(PROPERTY_TO_DPS_ID[ATTR_DISPLAY_ON])
         dps_display_on = self._device.get_property(PROPERTY_TO_DPS_ID[ATTR_DISPLAY_ON])
 
 
         if dps_hvac_mode != HVAC_MODE_TO_DPS_MODE[HVAC_MODE_OFF]:
         if dps_hvac_mode != HVAC_MODE_TO_DPS_MODE[HVAC_MODE_OFF]:
-            await self.async_turn_on() if not dps_display_on else await self.async_turn_off()
+            await (self.async_turn_on() if not dps_display_on else self.async_turn_off())
 
 
     async def async_update(self):
     async def async_update(self):
         await self._device.async_refresh()
         await self._device.async_refresh()

+ 21 - 8
custom_components/goldair_climate/heater/lock.py

@@ -1,9 +1,9 @@
 {
 {
-  "title": "Goldair Climate",
   "config": {
   "config": {
+    "title": "Goldair Climate",
     "step": {
     "step": {
       "user": {
       "user": {
-        "title": "Configure a Goldair climate device",
+        "title": "Configure your Goldair climate device",
         "description": "Please enter your device information.",
         "description": "Please enter your device information.",
         "data": {
         "data": {
           "name": "Name",
           "name": "Name",
@@ -11,16 +11,29 @@
           "device_id": "Device ID (uuid)",
           "device_id": "Device ID (uuid)",
           "local_key": "Local key",
           "local_key": "Local key",
           "type": "Device type",
           "type": "Device type",
-          "heater": "Heater",
-          "dehumidifier": "Dehumidifier",
-          "fan": "Fan",
-          "display_light": "Add LED display as light entity",
-          "child_lock": "Add child lock as lock entity"
+          "climate": "Add a climate entity",
+          "display_light": "Add LED display as a light entity",
+          "child_lock": "Add child lock as a lock entity"
         }
         }
       }
       }
     },
     },
     "abort": {
     "abort": {
-      "already_configured": "[%key:common.config_flow.abort.already_configured%]"
+      "already_configured": "A device with that ID has already been added."
+    }
+  },
+  "options": {
+    "step": {
+      "user": {
+        "title": "Configure your Goldair climate device",
+        "data": {
+          "name": "Name",
+          "host": "IP address or hostname",
+          "local_key": "Local key",
+          "climate": "Add a climate entity",
+          "display_light": "Add LED display as light entity",
+          "child_lock": "Add child lock as lock entity"
+        }
+      }
     }
     }
   }
   }
 }
 }

+ 39 - 0
custom_components/goldair_climate/translations/en.json

@@ -0,0 +1,39 @@
+{
+  "config": {
+    "title": "Goldair Climate",
+    "step": {
+      "user": {
+        "title": "Configure your Goldair climate device",
+        "description": "Please enter your device information.",
+        "data": {
+          "name": "Name",
+          "host": "IP address or hostname",
+          "device_id": "Device ID (uuid)",
+          "local_key": "Local key",
+          "type": "Device type",
+          "climate": "Add a climate entity",
+          "display_light": "Add LED display as a light entity",
+          "child_lock": "Add child lock as a lock entity"
+        }
+      }
+    },
+    "abort": {
+      "already_configured": "[%key:common.config_flow.abort.already_configured%]"
+    }
+  },
+  "options": {
+    "step": {
+      "user": {
+        "title": "Configure your Goldair climate device",
+        "data": {
+          "name": "Name",
+          "host": "IP address or hostname",
+          "local_key": "Local key",
+          "climate": "Add a climate entity",
+          "display_light": "Add LED display as light entity",
+          "child_lock": "Add child lock as lock entity"
+        }
+      }
+    }
+  }
+}