22
33import asyncio
44import logging
5+ from json import JSONDecodeError
56
67import aiohttp
78
2526class IntesisHomeLocal (IntesisBase ):
2627 """pyintesishome local class."""
2728
28- def __init__ (self , host , username , password , loop = None , websession = None ):
29+ def __init__ (self , host , username , password , loop = None , websession = None ) -> None :
2930 """Constructor"""
3031 device_type = DEVICE_INTESISHOME_LOCAL
3132 self ._session_id : str = ""
@@ -70,7 +71,7 @@ async def _run_updater(self):
7071 self ._update_device_state (self ._device_id , uid , value )
7172
7273 await self ._send_update_callback (self ._device_id )
73- except ( IHConnectionError ) as exc :
74+ except IHConnectionError as exc :
7475 _LOGGER .error ("Error during updater task: %s" , exc )
7576 await asyncio .sleep (self ._scan_interval )
7677 except asyncio .CancelledError :
@@ -83,14 +84,35 @@ async def _authenticate(self) -> bool:
8384 "command" : LOCAL_CMD_LOGIN ,
8485 "data" : {"username" : self ._username , "password" : self ._password },
8586 }
86- async with self ._web_session .post (
87- f"http://{ self ._host } /api.cgi" , json = payload
88- ) as response :
89- if response .status != 200 :
90- raise IHConnectionError ("HTTP response status is unexpected (not 200)" )
91- json_response = await response .json ()
92- self ._session_id = json_response ["data" ].get ("id" ).get ("sessionID" )
93- _LOGGER .debug ("Authenticated with new session ID %s" , self ._session_id )
87+ try :
88+ async with self ._web_session .post (
89+ f"http://{ self ._host } /api.cgi" , json = payload
90+ ) as response :
91+ if response .status != 200 :
92+ raise IHConnectionError (
93+ "HTTP response status is unexpected (not 200)"
94+ )
95+ json_response = await response .json ()
96+ # Check if the response has the expected format
97+ if (
98+ "data" in json_response
99+ and "id" in json_response ["data" ]
100+ and "sessionID" in json_response ["data" ]["id" ]
101+ ):
102+ self ._session_id = json_response ["data" ]["id" ]["sessionID" ]
103+ _LOGGER .debug (
104+ "Authenticated with new session ID %s" , self ._session_id
105+ )
106+ else :
107+ _LOGGER .error ("Unexpected response format during authentication" )
108+ except (
109+ aiohttp .ClientConnectionError ,
110+ aiohttp .ClientResponseError ,
111+ aiohttp .ClientPayloadError ,
112+ aiohttp .ContentTypeError ,
113+ JSONDecodeError ,
114+ ) as exception :
115+ _LOGGER .error ("Error during authentication: %s" , str (exception ))
94116
95117 async def _request (self , command : str , ** kwargs ) -> dict :
96118 """Make a request."""
@@ -105,7 +127,9 @@ async def _request(self, command: str, **kwargs) -> dict:
105127 "command" : command ,
106128 "data" : {"sessionID" : self ._session_id , ** kwargs },
107129 }
108- _LOGGER .debug ("Sending intesishome_local command %s to %s" , command , self ._host )
130+ _LOGGER .debug (
131+ "Sending intesishome_local command %s to %s" , command , self ._host
132+ )
109133 timeout = aiohttp .ClientTimeout (total = 10 )
110134 json_response = {}
111135 try :
@@ -116,9 +140,8 @@ async def _request(self, command: str, **kwargs) -> dict:
116140 ) as response :
117141 if response .status != 200 :
118142 raise IHConnectionError (
119- "HTTP response status is unexpected for %s (got %s, want 200)" ,
120- self ._host ,
121- response .status ,
143+ f"HTTP response status is unexpected for { self ._host } "
144+ "(got {response.status}, want 200)"
122145 )
123146 json_response = await response .json ()
124147 except asyncio .exceptions .TimeoutError as exc :
@@ -127,7 +150,7 @@ async def _request(self, command: str, **kwargs) -> dict:
127150 self ._host ,
128151 exc ,
129152 )
130- except ( aiohttp .ClientError ) as exc :
153+ except aiohttp .ClientError as exc :
131154 _LOGGER .error (
132155 "IntesisHome HTTP error for %s: %s" ,
133156 self ._host ,
@@ -147,25 +170,30 @@ async def _request(self, command: str, **kwargs) -> dict:
147170 # wonky, so log an error plus the entire response.
148171 if json_response .get ("success" , False ):
149172 return json_response .get ("data" )
150- elif "error" in json_response :
173+ if "error" in json_response :
151174 error = json_response ["error" ]
152175 if error .get ("code" ) in [1 , 5 ]:
153176 self ._session_id = ""
154- _LOGGER .debug ("Request failed for %s (code=%s, message=%r). Clearing session key to force re-authentication" ,
155- self ._host ,
156- error .get ("code" ),
157- error .get ("message" ),
158- )
177+ _LOGGER .debug (
178+ "Request failed for %s (code=%s, message=%r)."
179+ "Clearing session key to force re-authentication" ,
180+ self ._host ,
181+ error .get ("code" ),
182+ error .get ("message" ),
183+ )
159184 else :
160- _LOGGER .debug ("Request failed for %s (code=%s, message=%r). Error not handled." ,
161- self ._host ,
162- error .get ("code" ),
163- error .get ("message" ),
164- )
165- else :
166- _LOGGER .debug ("Request failed for %s - no 'success' or 'error' keys. json_response=%r" ,
185+ _LOGGER .debug (
186+ "Request failed for %s (code=%s, message=%r). Error not handled" ,
167187 self ._host ,
168- json_response )
188+ error .get ("code" ),
189+ error .get ("message" ),
190+ )
191+ else :
192+ _LOGGER .debug (
193+ "Request failed for %s - no 'success' or 'error' keys. json_response=%r" ,
194+ self ._host ,
195+ json_response ,
196+ )
169197
170198 async def _request_value (self , name : str ) -> dict :
171199 """Get entity value by uid."""
@@ -202,15 +230,15 @@ def _has_datapoint(self, datapoint: str):
202230 async def connect (self ):
203231 """Connect to the device and start periodic updater."""
204232 await self .poll_status ()
205- _LOGGER .debug ("Successful authenticated and polled. Fetching Datapoints. " )
233+ _LOGGER .debug ("Successful authenticated and polled. Fetching Datapoints" )
206234 await self .get_datapoints ()
207235 self ._connected = True
208- _LOGGER .debug ("Starting updater task. " )
236+ _LOGGER .debug ("Starting updater task" )
209237 self ._update_task = asyncio .create_task (self ._run_updater ())
210238
211239 async def stop (self ):
212240 """Disconnect and stop periodic updater."""
213- _LOGGER .debug ("Stopping updater task. " )
241+ _LOGGER .debug ("Stopping updater task" )
214242 await self ._cancel_task_if_exists (self ._update_task )
215243 self ._connected = False
216244
@@ -225,25 +253,36 @@ async def get_info(self) -> dict:
225253
226254 async def poll_status (self , sendcallback = False ):
227255 """Get device info for setup purposes."""
228- await self ._authenticate ()
229- info = await self .get_info ()
230- self ._device_id = info ["sn" ]
231- self ._controller_id = info ["sn" ].lower ()
232- self ._controller_name = f"{ self ._info ['deviceModel' ]} ({ info ['ownSSID' ]} )"
233- # Setup devices
234- self ._devices [self ._device_id ] = {
235- "name" : info ["ownSSID" ],
236- "widgets" : [],
237- "model" : info ["deviceModel" ],
238- }
256+ try :
257+ await self ._authenticate ()
258+ info = await self .get_info ()
259+
260+ # Extract device_id up to the first space, if there is a space
261+ raw_id = info .get ("sn" )
262+ if raw_id :
263+ device_id , * _ = raw_id .split (" " )
264+ self ._device_id = device_id
265+ self ._controller_id = device_id .lower ()
266+
267+ self ._controller_name = (
268+ f"{ self ._info .get ('deviceModel' )} ({ info .get ('ownSSID' )} )"
269+ )
270+ # Setup devices
271+ self ._devices [self ._device_id ] = {
272+ "name" : info .get ("ownSSID" ),
273+ "widgets" : [],
274+ "model" : info .get ("deviceModel" ),
275+ }
239276
240- await self .get_datapoints ()
241- _LOGGER .debug (repr (self ._devices ))
277+ await self .get_datapoints ()
278+ _LOGGER .debug (repr (self ._devices ))
242279
243- self ._update_device_state (self ._device_id , "acStatus" , info [ "acStatus" ] )
280+ self ._update_device_state (self ._device_id , "acStatus" , info . get ( "acStatus" ) )
244281
245- if sendcallback :
246- await self ._send_update_callback (str (self ._device_id ))
282+ if sendcallback :
283+ await self ._send_update_callback (str (self ._device_id ))
284+ except (IHConnectionError , KeyError ) as exception :
285+ _LOGGER .error ("Error during polling status: %s" , str (exception ))
247286
248287 def get_mode_list (self , device_id ) -> list :
249288 """Get possible entity modes."""
0 commit comments