__init__.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. """
  2. Platform for Goldair WiFi-connected heaters and panels.
  3. Based on sean6541/tuya-homeassistant for service call logic, and TarxBoy's
  4. investigation into Goldair's tuyapi statuses
  5. https://github.com/codetheweb/tuyapi/issues/31.
  6. """
  7. import logging
  8. import homeassistant.helpers.config_validation as cv
  9. import voluptuous as vol
  10. from homeassistant.const import CONF_HOST, CONF_NAME
  11. from homeassistant.helpers.discovery import async_load_platform
  12. from .const import (CONF_CHILD_LOCK, CONF_CLIMATE, CONF_DEVICE_ID,
  13. CONF_DISPLAY_LIGHT, CONF_LOCAL_KEY, CONF_TYPE,
  14. CONF_TYPE_DEHUMIDIFIER, CONF_TYPE_FAN, CONF_TYPE_HEATER)
  15. from .device import GoldairTuyaDevice
  16. _LOGGER = logging.getLogger(__name__)
  17. VERSION = "0.0.8"
  18. DOMAIN = "goldair_climate"
  19. DATA_GOLDAIR_CLIMATE = "data_goldair_climate"
  20. INDIVIDUAL_CONFIG_SCHEMA_TEMPLATE = [
  21. {"key": CONF_NAME, "type": str, "required": True},
  22. {"key": CONF_HOST, "type": str, "required": True},
  23. {"key": CONF_DEVICE_ID, "type": str, "required": True, "fixed": True},
  24. {"key": CONF_LOCAL_KEY, "type": str, "required": True},
  25. {
  26. "key": CONF_TYPE,
  27. "type": vol.In([CONF_TYPE_HEATER, CONF_TYPE_DEHUMIDIFIER, CONF_TYPE_FAN]),
  28. "required": True,
  29. "fixed": True,
  30. },
  31. {"key": CONF_CLIMATE, "type": bool, "required": False, "default": True},
  32. {"key": CONF_DISPLAY_LIGHT, "type": bool, "required": False, "default": False},
  33. {"key": CONF_CHILD_LOCK, "type": bool, "required": False, "default": False},
  34. ]
  35. def individual_config_schema(defaults={}, exclude_fixed=False):
  36. output = {}
  37. for prop in INDIVIDUAL_CONFIG_SCHEMA_TEMPLATE:
  38. if exclude_fixed and prop.get("fixed"):
  39. continue
  40. options = {}
  41. default = defaults.get(prop["key"], prop.get("default"))
  42. if default is not None:
  43. options["default"] = default
  44. key = (
  45. vol.Required(prop["key"], **options)
  46. if prop["required"]
  47. else vol.Optional(prop["key"], **options)
  48. )
  49. output[key] = prop["type"]
  50. return output
  51. CONFIG_SCHEMA = vol.Schema(
  52. {DOMAIN: vol.All(cv.ensure_list, [vol.Schema(individual_config_schema())])},
  53. extra=vol.ALLOW_EXTRA,
  54. )
  55. async def async_setup(hass, config):
  56. hass.data[DOMAIN] = {}
  57. for device_config in config.get(DOMAIN, []):
  58. setup_device(hass, device_config)
  59. discovery_info = {
  60. CONF_DEVICE_ID: device_config.get(CONF_DEVICE_ID),
  61. CONF_TYPE: device_config.get(CONF_TYPE),
  62. }
  63. if device_config.get(CONF_CLIMATE) == True:
  64. hass.async_create_task(
  65. async_load_platform(hass, "climate", DOMAIN, discovery_info, config)
  66. )
  67. if device_config.get(CONF_DISPLAY_LIGHT) == True:
  68. hass.async_create_task(
  69. async_load_platform(hass, "light", DOMAIN, discovery_info, config)
  70. )
  71. if device_config.get(CONF_CHILD_LOCK) == True:
  72. hass.async_create_task(
  73. async_load_platform(hass, "lock", DOMAIN, discovery_info, config)
  74. )
  75. return True
  76. async def async_setup_entry(hass, entry):
  77. config = {**entry.data, **entry.options}
  78. setup_device(hass, config)
  79. if config[CONF_CLIMATE] == True:
  80. hass.async_create_task(
  81. hass.config_entries.async_forward_entry_setup(entry, "climate")
  82. )
  83. if config[CONF_DISPLAY_LIGHT] == True:
  84. hass.async_create_task(
  85. hass.config_entries.async_forward_entry_setup(entry, "light")
  86. )
  87. if config[CONF_CHILD_LOCK] == True:
  88. hass.async_create_task(
  89. hass.config_entries.async_forward_entry_setup(entry, "lock")
  90. )
  91. entry.add_update_listener(async_update_entry)
  92. return True
  93. async def async_unload_entry(hass, entry):
  94. config = entry.data
  95. delete_device(hass, config)
  96. if config[CONF_CLIMATE] == True:
  97. await hass.config_entries.async_forward_entry_unload(entry, "climate")
  98. if config[CONF_DISPLAY_LIGHT] == True:
  99. await hass.config_entries.async_forward_entry_unload(entry, "light")
  100. if config[CONF_CHILD_LOCK] == True:
  101. await hass.config_entries.async_forward_entry_unload(entry, "lock")
  102. return True
  103. async def async_update_entry(hass, entry):
  104. await async_unload_entry(hass, entry)
  105. await async_setup_entry(hass, entry)
  106. def setup_device(hass, config):
  107. device = GoldairTuyaDevice(
  108. config.get(CONF_NAME),
  109. config.get(CONF_DEVICE_ID),
  110. config.get(CONF_HOST),
  111. config.get(CONF_LOCAL_KEY),
  112. hass,
  113. )
  114. hass.data[DOMAIN][config.get(CONF_DEVICE_ID)] = device
  115. def delete_device(hass, config):
  116. del hass.data[DOMAIN][config[CONF_DEVICE_ID]]