46
46
PROTOCOLS = {1 : "V1" , 2 : "V2" , 3 : "V3" }
47
47
STORAGE_PATH = f".storage/{ DOMAIN } "
48
48
49
- servers = {
49
+ SERVERS = {
50
50
1 : "MSmartHome" ,
51
51
2 : "美的美居" ,
52
52
3 : "Midea Air" ,
61
61
62
62
63
63
class ConfigFlow (config_entries .ConfigFlow , domain = DOMAIN ):
64
- _account = None
65
- _password = None
66
- _server = None
67
64
available_device = []
68
65
devices = {}
69
66
found_device = {}
70
67
supports = {}
71
68
unsorted = {}
69
+ account = {}
70
+ cloud = None
71
+ session = None
72
72
for device_type , device_info in MIDEA_DEVICES .items ():
73
73
unsorted [device_type ] = device_info ["name" ]
74
74
@@ -82,11 +82,27 @@ def _save_device_config(self, data: dict):
82
82
save_json (record_file , data )
83
83
84
84
def _load_device_config (self , device_id ):
85
- os .makedirs (self .hass .config .path (STORAGE_PATH ), exist_ok = True )
86
85
record_file = self .hass .config .path (f"{ STORAGE_PATH } /{ device_id } .json" )
87
86
json_data = load_json (record_file , default = {})
88
87
return json_data
89
88
89
+ def _save_account (self , account : dict ):
90
+ os .makedirs (self .hass .config .path (STORAGE_PATH ), exist_ok = True )
91
+ record_file = self .hass .config .path (f"{ STORAGE_PATH } /account.json" )
92
+ account [CONF_PASSWORD ] = format ((int (account [CONF_ACCOUNT ].encode ("utf-8" ).hex (), 16 ) ^
93
+ int (account [CONF_PASSWORD ].encode ("utf-8" ).hex (), 16 )), 'x' )
94
+ save_json (record_file , account )
95
+
96
+ def _load_account (self ):
97
+ record_file = self .hass .config .path (f"{ STORAGE_PATH } /account.json" )
98
+ json_data = load_json (record_file , default = {})
99
+ if CONF_ACCOUNT in json_data .keys ():
100
+ json_data [CONF_PASSWORD ] = bytes .fromhex (format ((
101
+ int (json_data [CONF_PASSWORD ], 16 ) ^
102
+ int (json_data [CONF_ACCOUNT ].encode ("utf-8" ).hex (), 16 )), 'X' )
103
+ ).decode ('UTF-8' )
104
+ return json_data
105
+
90
106
@staticmethod
91
107
def _check_storage_device (device : dict , storage_device : dict ):
92
108
if storage_device .get (CONF_SUBTYPE ) is None :
@@ -96,16 +112,6 @@ def _check_storage_device(device: dict, storage_device: dict):
96
112
return False
97
113
return True
98
114
99
- def _get_configured_account (self ):
100
- for entry in self ._async_current_entries ():
101
- if entry .data .get (CONF_TYPE ) == CONF_ACCOUNT :
102
- password = bytes .fromhex (format ((
103
- int (entry .data .get (CONF_PASSWORD ), 16 ) ^
104
- int (entry .data .get (CONF_ACCOUNT ).encode ("utf-8" ).hex (), 16 )
105
- ), 'X' )).decode ('UTF-8' )
106
- return entry .data .get (CONF_ACCOUNT ), password , servers [entry .data .get (CONF_SERVER )]
107
- return None , None , None
108
-
109
115
def _already_configured (self , device_id , ip_address ):
110
116
for entry in self ._async_current_entries ():
111
117
if device_id == entry .data .get (CONF_DEVICE_ID ) or ip_address == entry .data .get (CONF_IP_ADDRESS ):
@@ -131,34 +137,31 @@ async def async_step_user(self, user_input=None, error=None):
131
137
132
138
async def async_step_login (self , user_input = None , error = None ):
133
139
if user_input is not None :
134
- session = async_create_clientsession (self .hass )
135
- cloud = get_midea_cloud (
136
- session = session ,
137
- cloud_name = servers [user_input [CONF_SERVER ]],
138
- account = user_input [CONF_ACCOUNT ],
139
- password = user_input [CONF_PASSWORD ]
140
- )
141
- _LOGGER .debug (
142
- f"account = { user_input [CONF_ACCOUNT ]} , password = { user_input [CONF_PASSWORD ]} , server = { servers [user_input [CONF_SERVER ]]} " )
143
- if await cloud .login ():
144
- password = format ((int (user_input [CONF_ACCOUNT ].encode ("utf-8" ).hex (), 16 ) ^
145
- int (user_input [CONF_PASSWORD ].encode ("utf-8" ).hex (), 16 )), 'x' )
146
- return self .async_create_entry (
147
- title = f"{ user_input [CONF_ACCOUNT ]} " ,
148
- data = {
149
- CONF_TYPE : CONF_ACCOUNT ,
150
- CONF_ACCOUNT : user_input [CONF_ACCOUNT ],
151
- CONF_PASSWORD : password ,
152
- CONF_SERVER : user_input [CONF_SERVER ]
153
- })
140
+ if self .session is None :
141
+ self .session = async_create_clientsession (self .hass )
142
+ if self .cloud is None :
143
+ self .cloud = get_midea_cloud (
144
+ session = self .session ,
145
+ cloud_name = SERVERS [user_input [CONF_SERVER ]],
146
+ account = user_input [CONF_ACCOUNT ],
147
+ password = user_input [CONF_PASSWORD ]
148
+ )
149
+ if await self .cloud .login ():
150
+ self .account = {
151
+ CONF_ACCOUNT : user_input [CONF_ACCOUNT ],
152
+ CONF_PASSWORD : user_input [CONF_PASSWORD ],
153
+ CONF_SERVER : SERVERS [user_input [CONF_SERVER ]]
154
+ }
155
+ self ._save_account (self .account )
156
+ return await self .async_step_auto ()
154
157
else :
155
158
return await self .async_step_login (error = "login_failed" )
156
159
return self .async_show_form (
157
160
step_id = "login" ,
158
161
data_schema = vol .Schema ({
159
162
vol .Required (CONF_ACCOUNT ): str ,
160
163
vol .Required (CONF_PASSWORD ): str ,
161
- vol .Required (CONF_SERVER , default = 1 ): vol .In (servers )
164
+ vol .Required (CONF_SERVER , default = 1 ): vol .In (SERVERS )
162
165
}),
163
166
errors = {"base" : error } if error else None
164
167
)
@@ -181,9 +184,6 @@ async def async_step_list(self, user_input=None, error=None):
181
184
)
182
185
183
186
async def async_step_discovery (self , user_input = None , error = None ):
184
- self ._account , self ._password , self ._server = self ._get_configured_account ()
185
- if self ._account is None :
186
- return await self .async_step_login ()
187
187
if user_input is not None :
188
188
if user_input [CONF_IP_ADDRESS ].lower () == "auto" :
189
189
ip_address = None
@@ -228,8 +228,18 @@ async def async_step_auto(self, user_input=None, error=None):
228
228
_LOGGER .debug (f"Loaded configuration for device { device_id } from storage" )
229
229
return await self .async_step_manually ()
230
230
else :
231
- session = async_create_clientsession (self .hass )
232
- cloud = get_midea_cloud (self ._server , session , self ._account , self ._password )
231
+ if CONF_ACCOUNT not in self .account .keys ():
232
+ self .account = self ._load_account ()
233
+ if CONF_ACCOUNT not in self .account .keys ():
234
+ return await self .async_step_login ()
235
+ if self .session is None :
236
+ self .session = async_create_clientsession (self .hass )
237
+ if self .cloud is None :
238
+ self .cloud = get_midea_cloud (
239
+ self .account [CONF_SERVER ], self .session , self .account [CONF_ACCOUNT ],
240
+ self .account [CONF_PASSWORD ])
241
+ if not await self .cloud .login ():
242
+ return await self .async_step_login ()
233
243
self .found_device = {
234
244
CONF_DEVICE_ID : device_id ,
235
245
CONF_TYPE : device .get (CONF_TYPE ),
@@ -238,23 +248,22 @@ async def async_step_auto(self, user_input=None, error=None):
238
248
CONF_PORT : device .get (CONF_PORT ),
239
249
CONF_MODEL : device .get (CONF_MODEL ),
240
250
}
241
- if await cloud .login ():
242
- if device_info := await cloud .get_device_info (device_id ):
243
- self .found_device [CONF_NAME ] = device_info .get ("name" )
244
- self .found_device [CONF_SUBTYPE ] = device_info .get ("model_number" )
251
+ if device_info := await self .cloud .get_device_info (device_id ):
252
+ self .found_device [CONF_NAME ] = device_info .get ("name" )
253
+ self .found_device [CONF_SUBTYPE ] = device_info .get ("model_number" )
245
254
else :
246
255
return await self .async_step_auto (error = "login_failed" )
247
256
if device .get (CONF_PROTOCOL ) == 3 :
248
- if self ._server == "美的美居" :
257
+ if self .account [ CONF_SERVER ] == "美的美居" :
249
258
_LOGGER .debug (f"Try to get the Token and the Key use the preset MSmartHome account" )
250
- cloud = get_midea_cloud (
259
+ self . cloud = get_midea_cloud (
251
260
"MSmartHome" ,
252
- session ,
261
+ self . session ,
253
262
bytes .fromhex (format ((PRESET_ACCOUNT [0 ] ^ PRESET_ACCOUNT [1 ]), 'X' )).decode ('ASCII' ),
254
263
bytes .fromhex (format ((PRESET_ACCOUNT [0 ] ^ PRESET_ACCOUNT [2 ]), 'X' )).decode ('ASCII' ))
255
- if not await cloud .login ():
264
+ if not await self . cloud .login ():
256
265
return await self .async_step_auto (error = "preset_account" )
257
- keys = await cloud .get_keys (user_input [CONF_DEVICE ])
266
+ keys = await self . cloud .get_keys (user_input [CONF_DEVICE ])
258
267
for method , key in keys .items ():
259
268
dm = MiedaDevice (
260
269
name = "" ,
0 commit comments