Skip to content

Commit a784ca6

Browse files
committed
First step in OAuth2
* custom_components/daikin_residential_altherma/application_credentials.py: Added. * custom_components/daikin_residential_altherma/config_flow.py: * custom_components/daikin_residential_altherma/manifest.json:
1 parent 3b250e2 commit a784ca6

File tree

3 files changed

+69
-64
lines changed

3 files changed

+69
-64
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from homeassistant.core import HomeAssistant
2+
from homeassistant.components.application_credentials import AuthorizationServer
3+
4+
5+
async def async_get_authorization_server(hass: HomeAssistant) -> AuthorizationServer:
6+
"""Return authorization server."""
7+
return AuthorizationServer(
8+
authorize_url="https://idp.onecta.daikineurope.com/v1/oidc/authorize",
9+
token_url="https://idp.onecta.daikineurope.com/v1/oidc/token"
10+
)
Original file line numberDiff line numberDiff line change
@@ -1,79 +1,74 @@
11
"""Config flow for the Daikin platform."""
22
import logging
33

4-
import voluptuous as vol
4+
from collections.abc import Mapping
5+
from typing import Any
56

67
from homeassistant import config_entries
7-
from homeassistant.const import CONF_EMAIL, CONF_PASSWORD
8+
from homeassistant.const import CONF_ACCESS_TOKEN, CONF_TOKEN
9+
from homeassistant.helpers import config_entry_oauth2_flow
10+
from homeassistant.data_entry_flow import FlowResult
811

912
from .daikin_api import DaikinApi
10-
from .const import DOMAIN, CONF_TOKENSET
13+
from .const import DOMAIN
1114

15+
CONF_USER_ID = "user_id"
1216
_LOGGER = logging.getLogger(__name__)
1317

14-
15-
@config_entries.HANDLERS.register(DOMAIN)
16-
class FlowHandler(config_entries.ConfigFlow):
18+
class FlowHandler(
19+
config_entry_oauth2_flow.AbstractOAuth2FlowHandler,
20+
domain=DOMAIN,
21+
):
1722
"""Handle a config flow."""
18-
23+
"""See https://developers.home-assistant.io/docs/core/platform/application_credentials/ """
1924
VERSION = 1
25+
DOMAIN = DOMAIN
2026
CONNECTION_CLASS = config_entries.CONN_CLASS_CLOUD_POLL
2127

22-
def __init__(self):
23-
"""Initialize the Daikin config flow."""
24-
self.host = None
25-
2628
@property
27-
def schema(self):
28-
"""Return current schema."""
29-
return vol.Schema(
30-
{vol.Required(CONF_EMAIL): str, vol.Required(CONF_PASSWORD): str}
31-
)
32-
33-
async def _create_entry(self, email, password, tokenSet):
34-
"""Register new entry."""
35-
# if not self.unique_id:
36-
# await self.async_set_unique_id(password)
37-
# self._abort_if_unique_id_configured()
38-
if self._async_current_entries():
39-
return self.async_abort(reason="already_configured")
40-
41-
await self.async_set_unique_id("DaikinResidentialAltherma")
42-
return self.async_create_entry(
43-
title="Daikin",
44-
data={CONF_EMAIL: email, CONF_PASSWORD: password, CONF_TOKENSET: tokenSet},
45-
)
46-
47-
async def _attempt_connection(self, email, password):
48-
"""Create device."""
49-
try:
50-
daikin_api = DaikinApi(self.hass, None)
51-
except Exception as e:
52-
_LOGGER.error("Failed to initialize DaikinApi: %s", e)
53-
return self.async_abort(reason="init_failed")
54-
try:
55-
await daikin_api.retrieveAccessToken(email, password)
56-
except Exception as e:
57-
_LOGGER.error("Failed to retrieve Access Token: %s", e)
58-
return self.async_abort(reason="token_retrieval_failed")
59-
try:
60-
await daikin_api.getApiInfo()
61-
except Exception as e:
62-
_LOGGER.error("Failed to connect to DaikinApi: %s", e)
63-
return self.async_abort(reason="cannot_connect")
64-
65-
return await self._create_entry(email, password, daikin_api.tokenSet)
66-
67-
async def async_step_user(self, user_input=None):
68-
"""User initiated config flow."""
29+
def extra_authorize_data(self) -> dict[str, str]:
30+
"""Extra data that needs to be appended to the authorize url."""
31+
return {
32+
"scope": "openid,onecta:basic.integration",
33+
"redirect_uri": "daikinunified://login",
34+
}
35+
36+
async def async_oauth_create_entry(self, data: dict) -> FlowResult:
37+
"""Create an oauth config entry or update existing entry for reauth."""
38+
existing_entry = await self.async_set_unique_id(DOMAIN)
39+
if existing_entry:
40+
self.hass.config_entries.async_update_entry(existing_entry, data=data)
41+
await self.hass.config_entries.async_reload(existing_entry.entry_id)
42+
return self.async_abort(reason="reauth_successful")
43+
44+
return await super().async_oauth_create_entry(data)
45+
46+
47+
async def async_step_user(self, user_input: dict | None = None) -> FlowResult:
48+
"""Handle a flow start."""
49+
await self.async_set_unique_id(DOMAIN)
50+
51+
if (
52+
self.source != config_entries.SOURCE_REAUTH
53+
and self._async_current_entries()
54+
):
55+
return self.async_abort(reason="single_instance_allowed")
56+
57+
return await super().async_step_user(user_input)
58+
59+
async def async_step_reauth(self, entry_data: Mapping[str, Any]) -> FlowResult:
60+
"""Perform reauth upon an API authentication error."""
61+
return await self.async_step_reauth_confirm()
62+
63+
async def async_step_reauth_confirm(
64+
self, user_input: dict | None = None
65+
) -> FlowResult:
66+
"""Dialog that informs the user that reauth is required."""
6967
if user_input is None:
70-
return self.async_show_form(step_id="user", data_schema=self.schema)
71-
return await self._attempt_connection(
72-
user_input.get(CONF_EMAIL), user_input.get(CONF_PASSWORD)
73-
)
74-
75-
async def async_step_import(self, user_input):
76-
"""Import a config entry from YAML."""
77-
return await self._attempt_connection(
78-
user_input.get(CONF_EMAIL), user_input.get(CONF_PASSWORD)
79-
)
68+
return self.async_show_form(step_id="reauth_confirm")
69+
70+
71+
@property
72+
def logger(self) -> logging.Logger:
73+
"""Return logger."""
74+
return logging.getLogger(__name__)

custom_components/daikin_residential_altherma/manifest.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"@jwillemsen"
66
],
77
"config_flow": true,
8-
"dependencies": [],
8+
"dependencies": ["application_credentials"],
99
"documentation": "https://github.com/jwillemsen/daikin_residential_altherma",
1010
"iot_class": "cloud_polling",
1111
"issue_tracker": "https://github.com/jwillemsen/daikin_residential_altherma/issues",

0 commit comments

Comments
 (0)