1+ import base64
2+
13import homeassistant .helpers .config_validation as cv
24import voluptuous as vol
35from homeassistant .config_entries import ConfigEntry , ConfigFlow , OptionsFlow
68
79from .core import core_utils
810from .core .const import DOMAIN , PID_BLE , PID_WIFI , PID_WIFI_BLE
9- from .core .xiaomi_cloud import MiCloud
11+ from .core .xiaomi_cloud import AuthResult , MiCloud
1012from .hass import hass_utils
1113
1214SERVERS = {
1921}
2022
2123
22- def vol_schema (schema : dict , defaults : dict | None ) -> vol .Schema :
24+ def vol_schema (schema : dict , defaults : dict = None ) -> vol .Schema :
2325 if defaults :
2426 for key in schema :
2527 if (value := defaults .get (key .schema )) is not None :
@@ -30,6 +32,9 @@ def vol_schema(schema: dict, defaults: dict | None) -> vol.Schema:
3032class FlowHandler (ConfigFlow , domain = DOMAIN ):
3133 VERSION = 4
3234
35+ cloud : MiCloud = None
36+ cloud_user_input : dict = None
37+
3338 cloud_gateways : list [dict ] = None
3439
3540 async def async_step_user (self , user_input : dict = None ):
@@ -66,36 +71,74 @@ async def async_step_user(self, user_input: dict = None):
6671 ),
6772 )
6873
74+ def _show_cloud_form (self , defaults : dict , errors : dict = None ):
75+ return self .async_show_form (
76+ step_id = "cloud" ,
77+ data_schema = vol_schema (
78+ {
79+ vol .Required ("username" ): str ,
80+ vol .Required ("password" ): str ,
81+ vol .Required ("servers" , default = ["cn" ]): cv .multi_select (SERVERS ),
82+ },
83+ defaults ,
84+ ),
85+ errors = errors ,
86+ )
87+
88+ async def _process_cloud_result (self , result : AuthResult | None ):
89+ if result ["ok" ]:
90+ return self .async_create_entry (
91+ title = self .cloud_user_input ["username" ],
92+ data = {
93+ "username" : self .cloud_user_input ["username" ],
94+ "servers" : self .cloud_user_input ["servers" ],
95+ "token" : result ["token" ],
96+ },
97+ )
98+
99+ if image := result .get ("captcha" ):
100+ image = "data:image/jpeg;base64," + base64 .b64encode (image ).decode ()
101+ return self .async_show_form (
102+ step_id = "cloud_captcha" ,
103+ data_schema = vol_schema ({vol .Required ("code" ): str }),
104+ description_placeholders = {"image" : image },
105+ )
106+
107+ if email := result .get ("email" ):
108+ return self .async_show_form (
109+ step_id = "cloud_email" ,
110+ data_schema = vol_schema ({vol .Required ("code" ): str }),
111+ description_placeholders = {"email" : email },
112+ )
113+
114+ return self ._show_cloud_form (
115+ self .cloud_user_input , errors = {"base" : "cant_login" }
116+ )
117+
69118 async def async_step_cloud (self , user_input : dict = None ):
70- kwargs = {"description_placeholders" : {"verify" : "" }}
119+ if not user_input :
120+ return self ._show_cloud_form (user_input )
71121
72- if user_input :
73- if user_input ["servers" ]:
74- session = async_create_clientsession (self .hass )
75- cloud = MiCloud (session )
76- if await cloud .login (user_input ["username" ], user_input ["password" ]):
77- return self .async_create_entry (
78- title = user_input ["username" ], data = user_input
79- )
80- elif cloud .verify :
81- msg = f"\n [Verify url]({ cloud .verify } )"
82- kwargs ["description_placeholders" ]["verify" ] = msg
83- kwargs ["errors" ] = {"base" : "verify" }
84- else :
85- kwargs ["errors" ] = {"base" : "cant_login" }
86- else :
87- kwargs ["errors" ] = {"base" : "no_servers" }
122+ if not user_input ["servers" ]:
123+ return self ._show_cloud_form (user_input , {"base" : "no_servers" })
88124
89- data = vol_schema (
90- {
91- vol . Required ( "username" ): str ,
92- vol . Required ( "password" ): str ,
93- vol . Required ( "servers" , default = [ "cn" ]): cv . multi_select ( SERVERS ),
94- },
95- user_input ,
125+ if not self . cloud :
126+ self . cloud = MiCloud ( async_create_clientsession ( self . hass ))
127+
128+ self . cloud_user_input = user_input
129+
130+ result = await self . cloud . login (
131+ user_input [ "username" ], self . cloud_user_input [ "password" ]
96132 )
133+ return await self ._process_cloud_result (result )
134+
135+ async def async_step_cloud_captcha (self , user_input : dict = None ):
136+ result = await self .cloud .login_captcha (user_input ["code" ])
137+ return await self ._process_cloud_result (result )
97138
98- return self .async_show_form (step_id = "cloud" , data_schema = data , ** kwargs )
139+ async def async_step_cloud_email (self , user_input : dict = None ):
140+ result = await self .cloud .verify_email (user_input ["code" ])
141+ return await self ._process_cloud_result (result )
99142
100143 async def async_step_token (self , user_input : dict = None ):
101144 """GUI > Configuration > Integrations > Plus > Xiaomi Gateway 3"""
0 commit comments