Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 25 additions & 22 deletions homeassistant/components/daikin/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,18 @@
COMPONENT_TYPES = ["climate", "sensor", "switch"]

CONFIG_SCHEMA = vol.Schema(
{
DOMAIN: vol.Schema(
{vol.Optional(CONF_HOSTS, default=[]): vol.All(cv.ensure_list, [cv.string])}
)
},
vol.All(
cv.deprecated(DOMAIN, invalidation_version="0.112.0"),
{
DOMAIN: vol.Schema(
{
vol.Optional(CONF_HOSTS, default=[]): vol.All(
cv.ensure_list, [cv.string]
)
}
)
},
),
extra=vol.ALLOW_EXTRA,
)

Expand Down Expand Up @@ -60,14 +67,7 @@ async def async_setup(hass, config):

async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry):
"""Establish connection with Daikin."""
conf = entry.data
daikin_api = await daikin_api_setup(
hass,
conf[CONF_HOST],
conf.get(CONF_KEY),
conf.get(CONF_UUID),
conf.get(CONF_PASSWORD),
)
daikin_api = await daikin_api_setup(hass, entry)
if not daikin_api:
return False
hass.data.setdefault(DOMAIN, {}).update({entry.entry_id: daikin_api})
Expand All @@ -92,36 +92,39 @@ async def async_unload_entry(hass, config_entry):
return True


async def daikin_api_setup(hass, host, key, uuid, password):
async def daikin_api_setup(hass, entry):
"""Create a Daikin instance only once."""

session = hass.helpers.aiohttp_client.async_get_clientsession()
try:
with timeout(TIMEOUT):
device = await Appliance.factory(
host, session, key=key, uuid=uuid, password=password
device_id=entry.data[CONF_HOST],
session=hass.helpers.aiohttp_client.async_get_clientsession(),
key=entry.data.get(CONF_KEY),
uuid=entry.data.get(CONF_UUID),
password=entry.data.get(CONF_PASSWORD),
)
except asyncio.TimeoutError:
_LOGGER.debug("Connection to %s timed out", host)
_LOGGER.debug("Connection to %s timed out", entry.data[CONF_HOST])
raise ConfigEntryNotReady
except ClientConnectionError:
_LOGGER.debug("ClientConnectionError to %s", host)
_LOGGER.debug("ClientConnectionError to %s", entry.data[CONF_HOST])
raise ConfigEntryNotReady
except Exception: # pylint: disable=broad-except
_LOGGER.error("Unexpected error creating device %s", host)
_LOGGER.error("Unexpected error creating device %s", entry.data[CONF_HOST])
return None

api = DaikinApi(device)
api = DaikinApi(device, entry)

return api


class DaikinApi:
"""Keep the Daikin instance in one place and centralize the update."""

def __init__(self, device: Appliance):
def __init__(self, device: Appliance, entry: ConfigEntry):
"""Initialize the Daikin Handle."""
self.device = device
self.entry = entry
self.name = device.values.get("name", "Daikin AC")
self.ip_address = device.device_ip
self._available = True
Expand Down
7 changes: 6 additions & 1 deletion homeassistant/components/daikin/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
ATTR_STATE_OFF,
ATTR_STATE_ON,
ATTR_TARGET_TEMPERATURE,
CONF_TEMPERATURE_STEPS,
)

_LOGGER = logging.getLogger(__name__)
Expand Down Expand Up @@ -130,7 +131,9 @@ async def _set(self, settings):
# temperature
elif attr == ATTR_TEMPERATURE:
try:
values[HA_ATTR_TO_DAIKIN[ATTR_TARGET_TEMPERATURE]] = str(int(value))
values[HA_ATTR_TO_DAIKIN[ATTR_TARGET_TEMPERATURE]] = str(
float(value)
)
except ValueError:
_LOGGER.error("Invalid temperature %s", value)

Expand Down Expand Up @@ -170,6 +173,8 @@ def target_temperature(self):
@property
def target_temperature_step(self):
"""Return the supported step of target temperature."""
if self._api.entry.options.get(CONF_TEMPERATURE_STEPS):
return 0.5
return 1

async def async_set_temperature(self, **kwargs):
Expand Down
98 changes: 76 additions & 22 deletions homeassistant/components/daikin/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,12 @@

from homeassistant import config_entries
from homeassistant.const import CONF_HOST, CONF_PASSWORD
from homeassistant.core import callback

from .const import CONF_KEY, CONF_UUID, KEY_IP, KEY_MAC, TIMEOUT
from .const import CONF_KEY, CONF_TEMPERATURE_STEPS, CONF_UUID, KEY_IP, KEY_MAC, TIMEOUT

_LOGGER = logging.getLogger(__name__)

DATA_SCHEMA = vol.Schema(
{
vol.Required(CONF_HOST): str,
vol.Optional(CONF_KEY): str,
vol.Optional(CONF_PASSWORD): str,
}
)


@config_entries.HANDLERS.register("daikin")
class FlowHandler(config_entries.ConfigFlow):
Expand All @@ -31,12 +24,31 @@ class FlowHandler(config_entries.ConfigFlow):
VERSION = 1
CONNECTION_CLASS = config_entries.CONN_CLASS_LOCAL_POLL

def _create_entry(self, host, mac, key=None, uuid=None, password=None):
def __init__(self):
"""Initialize the Daikin config flow."""
self.host = None

@property
def _schema(self):
"""Return current schema."""
return vol.Schema(
{
vol.Required(CONF_HOST, default=self.host): str,
vol.Optional(CONF_KEY): str,
vol.Optional(CONF_PASSWORD): str,
}
)

@staticmethod
@callback
def async_get_options_flow(config_entry):
"""Get the options flow for this handler."""
return DaikinOptionsFlowHandler(config_entry)

async def _create_entry(self, host, mac, key=None, uuid=None, password=None):
"""Register new entry."""
# Check if mac already is registered
for entry in self._async_current_entries():
if entry.data[KEY_MAC] == mac:
return self.async_abort(reason="already_configured")
await self.async_set_unique_id(mac)
self._abort_if_unique_id_configured()

return self.async_create_entry(
title=host,
Expand Down Expand Up @@ -73,31 +85,35 @@ async def _create_device(self, host, key=None, password=None):
except asyncio.TimeoutError:
return self.async_show_form(
step_id="user",
data_schema=DATA_SCHEMA,
data_schema=self._schema,
errors={"base": "device_timeout"},
)
except web_exceptions.HTTPForbidden:
return self.async_show_form(
step_id="user", data_schema=DATA_SCHEMA, errors={"base": "forbidden"},
step_id="user", data_schema=self._schema, errors={"base": "forbidden"},
)
except ClientError:
_LOGGER.exception("ClientError")
return self.async_show_form(
step_id="user", data_schema=DATA_SCHEMA, errors={"base": "device_fail"},
step_id="user",
data_schema=self._schema,
errors={"base": "device_fail"},
)
except Exception: # pylint: disable=broad-except
_LOGGER.exception("Unexpected error creating device")
return self.async_show_form(
step_id="user", data_schema=DATA_SCHEMA, errors={"base": "device_fail"},
step_id="user",
data_schema=self._schema,
errors={"base": "device_fail"},
)

mac = device.mac
return self._create_entry(host, mac, key, uuid, password)
return await self._create_entry(host, mac, key, uuid, password)

async def async_step_user(self, user_input=None):
"""User initiated config flow."""
if user_input is None:
return self.async_show_form(step_id="user", data_schema=DATA_SCHEMA,)
return self.async_show_form(step_id="user", data_schema=self._schema)
return await self._create_device(
user_input[CONF_HOST],
user_input.get(CONF_KEY),
Expand All @@ -113,5 +129,43 @@ async def async_step_import(self, user_input):

async def async_step_discovery(self, user_input):
"""Initialize step from discovery."""
_LOGGER.info("Discovered device: %s", user_input)
return self._create_entry(user_input[KEY_IP], user_input[KEY_MAC])
_LOGGER.info("Discovered device: %s, %s", user_input[KEY_IP], user_input)
await self.async_set_unique_id(user_input[KEY_MAC])
self._abort_if_unique_id_configured()
self.host = user_input[KEY_IP]
return await self.async_step_user()

async def async_step_zeroconf(self, discovery_info):
"""Prepare configuration for a discovered Daikin device."""
_LOGGER.info("Zeroconf discovery_info: %s", discovery_info)
await self.async_set_unique_id(discovery_info.get(CONF_HOST))
self._abort_if_unique_id_configured()
self.host = discovery_info.get(CONF_HOST)
return await self.async_step_user()


class DaikinOptionsFlowHandler(config_entries.OptionsFlow):
"""Handle Daikin client options."""

def __init__(self, config_entry):
"""Initialize Daikin options flow."""
self.config_entry = config_entry

async def async_step_init(self, user_input=None):
"""Manage the Daikin options."""
if user_input is not None:
return self.async_create_entry(title="", data=user_input)

return self.async_show_form(
step_id="init",
data_schema=vol.Schema(
{
vol.Required(
CONF_TEMPERATURE_STEPS,
default=self.config_entry.options.get(
CONF_TEMPERATURE_STEPS, False
),
): bool
}
),
)
1 change: 1 addition & 0 deletions homeassistant/components/daikin/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
CONF_KEY = "key"
CONF_UUID = "uuid"

CONF_TEMPERATURE_STEPS = "temperature_steps"
KEY_MAC = "mac"
KEY_IP = "ip"

Expand Down
3 changes: 2 additions & 1 deletion homeassistant/components/daikin/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
"name": "Daikin AC",
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/daikin",
"requirements": ["pydaikin==2.0.1"],
"requirements": ["pydaikin==2.0.2"],
"codeowners": ["@fredrike"],
"zeroconf": ["_dkapi._tcp.local."],
"quality_scale": "platinum"
}
12 changes: 11 additions & 1 deletion homeassistant/components/daikin/strings.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
{
"options": {
"step": {
"init": {
"title": "Configure options for Daikin",
"data": {
"temperature_steps": "Use 0.5 steps for target temperature (default is 1.0)."
}
}
}
},
"config": {
"step": {
"user": {
"title": "Configure Daikin AC",
"description": "Enter IP address of your Daikin AC.",
"description": "Enter IP address of your Daikin AC.\n\nNote that [%key:common::config_flow::data::api_key%] and [%key:common::config_flow::data::password%] are used by BRP072Cxx and SKYFi devices respectively.",
"data": {
"host": "[%key:common::config_flow::data::host%]",
"key": "[%key:common::config_flow::data::api_key%]",
Expand Down
3 changes: 3 additions & 0 deletions homeassistant/generated/zeroconf.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
"_daap._tcp.local.": [
"forked_daapd"
],
"_dkapi._tcp.local.": [
"daikin"
],
"_elg._tcp.local.": [
"elgato"
],
Expand Down
2 changes: 1 addition & 1 deletion requirements_all.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1263,7 +1263,7 @@ pycsspeechtts==1.0.3
# pycups==1.9.73

# homeassistant.components.daikin
pydaikin==2.0.1
pydaikin==2.0.2

# homeassistant.components.danfoss_air
pydanfossair==0.1.0
Expand Down
2 changes: 1 addition & 1 deletion requirements_test_all.txt
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,7 @@ pychromecast==5.2.0
pycoolmasternet==0.0.4

# homeassistant.components.daikin
pydaikin==2.0.1
pydaikin==2.0.2

# homeassistant.components.deconz
pydeconz==70
Expand Down
Loading