Skip to content
Merged
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
36 changes: 18 additions & 18 deletions homeassistant/components/daikin/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,18 @@

from aiohttp import ClientConnectionError
from async_timeout import timeout
from pydaikin.appliance import Appliance
from pydaikin.daikin_base import Appliance
import voluptuous as vol

from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
from homeassistant.const import CONF_HOST, CONF_HOSTS
from homeassistant.const import CONF_HOST, CONF_HOSTS, CONF_PASSWORD
from homeassistant.exceptions import ConfigEntryNotReady
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC
from homeassistant.helpers.typing import HomeAssistantType
from homeassistant.util import Throttle

from . import config_flow # noqa: F401
from .const import TIMEOUT
from .const import CONF_KEY, CONF_UUID, TIMEOUT

_LOGGER = logging.getLogger(__name__)

Expand Down Expand Up @@ -62,7 +61,13 @@ 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])
daikin_api = await daikin_api_setup(
hass,
conf[CONF_HOST],
conf.get(CONF_KEY),
conf.get(CONF_UUID),
conf.get(CONF_PASSWORD),
)
if not daikin_api:
return False
hass.data.setdefault(DOMAIN, {}).update({entry.entry_id: daikin_api})
Expand All @@ -87,14 +92,15 @@ async def async_unload_entry(hass, config_entry):
return True


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

session = hass.helpers.aiohttp_client.async_get_clientsession()
try:
with timeout(TIMEOUT):
device = Appliance(host, session)
await device.init()
device = await Appliance.factory(
host, session, key=key, uuid=uuid, password=password
)
except asyncio.TimeoutError:
_LOGGER.debug("Connection to %s timed out", host)
raise ConfigEntryNotReady
Expand All @@ -116,8 +122,8 @@ class DaikinApi:
def __init__(self, device):
"""Initialize the Daikin Handle."""
self.device = device
self.name = device.values["name"]
self.ip_address = device.ip
self.name = device.values.get("name", "Daikin AC")
self.ip_address = device.device_ip
self._available = True

@Throttle(MIN_TIME_BETWEEN_UPDATES)
Expand All @@ -135,20 +141,14 @@ def available(self) -> bool:
"""Return True if entity is available."""
return self._available

@property
def mac(self):
"""Return mac-address of device."""
return self.device.values.get(CONNECTION_NETWORK_MAC)

@property
def device_info(self):
"""Return a device description for device registry."""
info = self.device.values
return {
"connections": {(CONNECTION_NETWORK_MAC, self.mac)},
"identifieres": self.mac,
"identifieres": self.device.mac,
"manufacturer": "Daikin",
"model": info.get("model"),
"name": info.get("name"),
"sw_version": info.get("ver").replace("_", "."),
"sw_version": info.get("ver", "").replace("_", "."),
}
10 changes: 2 additions & 8 deletions homeassistant/components/daikin/climate.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"""Support for the Daikin HVAC."""
import logging

from pydaikin import appliance
import voluptuous as vol

from homeassistant.components.climate import PLATFORM_SCHEMA, ClimateEntity
Expand Down Expand Up @@ -96,12 +95,7 @@ def __init__(self, api):
self._list = {
ATTR_HVAC_MODE: list(HA_STATE_TO_DAIKIN),
ATTR_FAN_MODE: self._api.device.fan_rate,
ATTR_SWING_MODE: list(
map(
str.title,
appliance.daikin_values(HA_ATTR_TO_DAIKIN[ATTR_SWING_MODE]),
)
),
ATTR_SWING_MODE: self._api.device.swing_modes,
}

self._supported_features = SUPPORT_TARGET_TEMPERATURE
Expand Down Expand Up @@ -156,7 +150,7 @@ def name(self):
@property
def unique_id(self):
"""Return a unique ID."""
return self._api.mac
return self._api.device.mac

@property
def temperature_unit(self):
Expand Down
64 changes: 49 additions & 15 deletions homeassistant/components/daikin/config_flow.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
"""Config flow for the Daikin platform."""
import asyncio
import logging
from uuid import uuid4

from aiohttp import ClientError
from async_timeout import timeout
from pydaikin.appliance import Appliance
from pydaikin.daikin_base import Appliance
import voluptuous as vol

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

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

_LOGGER = logging.getLogger(__name__)

Expand All @@ -22,24 +23,46 @@ class FlowHandler(config_entries.ConfigFlow):
VERSION = 1
CONNECTION_CLASS = config_entries.CONN_CLASS_LOCAL_POLL

async def _create_entry(self, host, mac):
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")

return self.async_create_entry(title=host, data={CONF_HOST: host, KEY_MAC: mac})
return self.async_create_entry(
title=host,
data={
CONF_HOST: host,
KEY_MAC: mac,
CONF_KEY: key,
CONF_UUID: uuid,
CONF_PASSWORD: password,
},
)

async def _create_device(self, host):
async def _create_device(self, host, key=None, password=None):
"""Create device."""

# BRP07Cxx devices needs uuid together with key
if key:
uuid = str(uuid4())
else:
uuid = None
key = None

if not password:
password = None

try:
device = Appliance(
host, self.hass.helpers.aiohttp_client.async_get_clientsession()
)
with timeout(TIMEOUT):
await device.init()
device = await Appliance.factory(
host,
self.hass.helpers.aiohttp_client.async_get_clientsession(),
key=key,
uuid=uuid,
password=password,
)
except asyncio.TimeoutError:
return self.async_abort(reason="device_timeout")
except ClientError:
Expand All @@ -49,16 +72,27 @@ async def _create_device(self, host):
_LOGGER.exception("Unexpected error creating device")
return self.async_abort(reason="device_fail")

mac = device.values.get("mac")
return await self._create_entry(host, mac)
mac = device.mac
return 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=vol.Schema({vol.Required(CONF_HOST): str})
step_id="user",
data_schema=vol.Schema(
{
vol.Required(CONF_HOST): str,
vol.Optional(CONF_KEY): str,
vol.Optional(CONF_PASSWORD): str,
}
),
)
return await self._create_device(user_input[CONF_HOST])
return await self._create_device(
user_input[CONF_HOST],
user_input.get(CONF_KEY),
user_input.get(CONF_PASSWORD),
)

async def async_step_import(self, user_input):
"""Import a config entry."""
Expand All @@ -70,4 +104,4 @@ 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 await self._create_entry(user_input[KEY_IP], user_input[KEY_MAC])
return self._create_entry(user_input[KEY_IP], user_input[KEY_MAC])
3 changes: 3 additions & 0 deletions homeassistant/components/daikin/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
},
}

CONF_KEY = "key"
CONF_UUID = "uuid"

KEY_MAC = "mac"
KEY_IP = "ip"

Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/daikin/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"name": "Daikin AC",
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/daikin",
"requirements": ["pydaikin==1.6.3"],
"requirements": ["pydaikin==2.0.0"],
"codeowners": ["@fredrike"],
"quality_scale": "platinum"
}
2 changes: 1 addition & 1 deletion homeassistant/components/daikin/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def __init__(self, api, monitored_state) -> None:
@property
def unique_id(self):
"""Return a unique ID."""
return f"{self._api.mac}-{self._device_attribute}"
return f"{self._api.device.mac}-{self._device_attribute}"

@property
def icon(self):
Expand Down
6 changes: 5 additions & 1 deletion homeassistant/components/daikin/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@
"user": {
"title": "Configure Daikin AC",
"description": "Enter IP address of your Daikin AC.",
"data": { "host": "Host" }
"data": {
"host": "Host",
"key": "Authentication key (only used by BRP072C/Zena devices)",
"password": "Device password (only used by SKYFi devices)"
}
}
},
"abort": {
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/daikin/switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def __init__(self, daikin_api, zone_id):
@property
def unique_id(self):
"""Return a unique ID."""
return f"{self._api.mac}-zone{self._zone_id}"
return f"{self._api.device.mac}-zone{self._zone_id}"

@property
def icon(self):
Expand Down
4 changes: 3 additions & 1 deletion homeassistant/components/daikin/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
"step": {
"user": {
"data": {
"host": "Host"
"host": "Host",
"key": "Authentication key (only used by BRP072C/Zena devices)",
"password": "Device password (only used by SKYFi devices)"
},
"description": "Enter IP address of your Daikin AC.",
"title": "Configure Daikin AC"
Expand Down
2 changes: 1 addition & 1 deletion requirements_all.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1242,7 +1242,7 @@ pycsspeechtts==1.0.3
# pycups==1.9.73

# homeassistant.components.daikin
pydaikin==1.6.3
pydaikin==2.0.0

# 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 @@ -512,7 +512,7 @@ pychromecast==5.0.0
pycoolmasternet==0.0.4

# homeassistant.components.daikin
pydaikin==1.6.3
pydaikin==2.0.0

# homeassistant.components.deconz
pydeconz==70
Expand Down
12 changes: 6 additions & 6 deletions tests/components/daikin/test_config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from homeassistant.components.daikin.const import KEY_IP, KEY_MAC
from homeassistant.const import CONF_HOST

from tests.async_mock import patch
from tests.async_mock import PropertyMock, patch
from tests.common import MockConfigEntry

MAC = "AABBCCDDEEFF"
Expand All @@ -27,13 +27,13 @@ def init_config_flow(hass):
def mock_daikin():
"""Mock pydaikin."""

async def mock_daikin_init():
async def mock_daikin_factory(*args, **kwargs):
"""Mock the init function in pydaikin."""
pass
return Appliance

with patch("homeassistant.components.daikin.config_flow.Appliance") as Appliance:
Appliance().values.get.return_value = "AABBCCDDEEFF"
Appliance().init = mock_daikin_init
type(Appliance).mac = PropertyMock(return_value="AABBCCDDEEFF")
Appliance.factory.side_effect = mock_daikin_factory
yield Appliance


Expand Down Expand Up @@ -95,7 +95,7 @@ async def test_discovery(hass, mock_daikin):
async def test_device_abort(hass, mock_daikin, s_effect, reason):
"""Test device abort."""
flow = init_config_flow(hass)
mock_daikin.side_effect = s_effect
mock_daikin.factory.side_effect = s_effect
Comment thread
fredrike marked this conversation as resolved.

result = await flow.async_step_user({CONF_HOST: HOST})
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
Expand Down