99import aiohttp # type: ignore
1010
1111from .const import MAX_AMPS , MIN_AMPS
12- from .exceptions import AuthenticationError , ParseJSONError
12+ from .exceptions import (
13+ AlreadyListening ,
14+ AuthenticationError ,
15+ MissingMethod ,
16+ ParseJSONError ,
17+ UnknownError ,
18+ )
1319
1420_LOGGER = logging .getLogger (__name__ )
1521
@@ -116,7 +122,7 @@ async def running(self):
116122 break
117123
118124 except aiohttp .ClientResponseError as error :
119- if error .code == 401 :
125+ if error .status == 401 :
120126 _LOGGER .error ("Credentials rejected: %s" , error )
121127 self ._error_reason = ERROR_AUTH_FAILURE
122128 else :
@@ -174,70 +180,82 @@ def __init__(self, host: str, user: str = None, pwd: str = None) -> None:
174180 self .callback : Optional [Callable ] = None
175181 self ._loop = None
176182
177- async def send_command (self , command : str ) -> tuple | None :
178- """Send a RAPI command to the charger and parses the response."""
183+ async def process_request (
184+ self , url : str , method : str = None , data : Any = None
185+ ) -> Any :
186+ """Return result of processed HTTP request."""
179187 auth = None
180- url = f" { self . url } r"
181- data = { "json" : 1 , "rapi" : command }
188+ if method is None :
189+ raise MissingMethod
182190
183191 if self ._user and self ._pwd :
184192 auth = aiohttp .BasicAuth (self ._user , self ._pwd )
185193
186- _LOGGER .debug ("Posting data: %s to %s" , command , url )
187194 async with aiohttp .ClientSession () as session :
188- async with session .post (url , data = data , auth = auth ) as resp :
195+ http_method = getattr (session , method )
196+ async with http_method (url , data = data , auth = auth ) as resp :
197+ try :
198+ message = await resp .json ()
199+ except TimeoutError :
200+ _LOGGER .error ("%s: %s" , ERROR_TIMEOUT , url )
201+
189202 if resp .status == 400 :
190- _LOGGER .debug ( "JSON error: %s" , await resp . text () )
203+ _LOGGER .error ( " %s" , message [ "msg" ] )
191204 raise ParseJSONError
192205 if resp .status == 401 :
193- _LOGGER .debug ("Authentication error: %s" , await resp .text ())
206+ error = await resp .text ()
207+ _LOGGER .error ("Authentication error: %s" , error )
194208 raise AuthenticationError
209+ if resp .status == 404 :
210+ _LOGGER .error ("%s" , message ["msg" ])
211+ raise UnknownError
212+ if resp .status == 405 :
213+ _LOGGER .error ("%s" , message ["msg" ])
214+ elif resp .status == 500 :
215+ _LOGGER .error ("%s" , message ["msg" ])
195216
196- value = await resp . json ()
217+ return message
197218
198- if "ret" not in value :
199- return False , ""
200- return value ["cmd" ], value ["ret" ]
219+ async def send_command (self , command : str ) -> tuple | None :
220+ """Send a RAPI command to the charger and parses the response."""
221+ url = f"{ self .url } r"
222+ data = {"json" : 1 , "rapi" : command }
223+
224+ _LOGGER .debug ("Posting data: %s to %s" , command , url )
225+ value = await self .process_request (url = url , method = "post" , data = data )
226+ if "ret" not in value :
227+ return False , ""
228+ return value ["cmd" ], value ["ret" ]
201229
202230 async def update (self ) -> None :
203231 """Update the values."""
204- auth = None
205232 urls = [f"{ self .url } config" ]
206233
207- if self ._user and self ._pwd :
208- auth = aiohttp .BasicAuth (self ._user , self ._pwd )
209-
210234 if not self ._ws_listening :
211235 urls = [f"{ self .url } status" , f"{ self .url } config" ]
212236
213- async with aiohttp .ClientSession () as session :
214- for url in urls :
215- _LOGGER .debug ("Updating data from %s" , url )
216- async with session .get (url , auth = auth ) as resp :
217- if resp .status == 401 :
218- _LOGGER .debug ("Authentication error: %s" , resp .text ())
219- raise AuthenticationError
220-
221- if "/status" in url :
222- try :
223- self ._status = await resp .json ()
224- _LOGGER .debug ("Status update: %s" , self ._status )
225- except TimeoutError :
226- _LOGGER .error ("%s status." , ERROR_TIMEOUT )
227- else :
228- try :
229- self ._config = await resp .json ()
230- _LOGGER .debug ("Config update: %s" , self ._config )
231- except TimeoutError :
232- _LOGGER .error ("%s config." , ERROR_TIMEOUT )
237+ for url in urls :
238+ _LOGGER .debug ("Updating data from %s" , url )
239+ response = await self .process_request (url , method = "get" )
240+ if "/status" in url :
241+ self ._status = response
242+ _LOGGER .debug ("Status update: %s" , self ._status )
243+
244+ else :
245+ self ._config = response
246+ _LOGGER .debug ("Config update: %s" , self ._config )
233247
234248 if not self .websocket :
235249 # Start Websocket listening
236250 self .websocket = OpenEVSEWebsocket (
237251 self .url , self ._update_status , self ._user , self ._pwd
238252 )
239- if not self ._ws_listening :
240- self ._start_listening ()
253+
254+ def ws_start (self ):
255+ """Start the websocket listener."""
256+ if self ._ws_listening :
257+ raise AlreadyListening
258+ self ._start_listening ()
241259
242260 def _start_listening (self ):
243261 """Start the websocket listener."""
@@ -283,7 +301,7 @@ def _update_status(self, msgtype, data, error):
283301 self ._status .update (data )
284302
285303 if self .callback is not None :
286- self .callback ()
304+ self .callback () # pylint: disable=not-callable
287305
288306 def ws_disconnect (self ) -> None :
289307 """Disconnect the websocket listener."""
@@ -297,28 +315,39 @@ def ws_state(self) -> Any:
297315 assert self .websocket
298316 return self .websocket .state
299317
318+ async def get_schedule (self ) -> list :
319+ """Return the current schedule."""
320+ url = f"{ self .url } schedule"
321+
322+ _LOGGER .debug ("Getting current schedule from %s" , url )
323+ response = await self .process_request (url = url , method = "post" )
324+ return response
325+
326+ async def set_charge_mode (self , mode : str = "fast" ) -> None :
327+ """Set the charge mode."""
328+ url = f"{ self .url } config"
329+
330+ if mode != "fast" or mode != "eco" :
331+ _LOGGER .error ("Invalid value for charge_mode: %s" , mode )
332+ raise ValueError
333+
334+ data = {"charge_mode" : mode }
335+
336+ _LOGGER .debug ("Setting charge mode to %s" , mode )
337+ response = await self .process_request (
338+ url = url , method = "post" , data = data
339+ ) # noqa: E501
340+ if response ["msg" ] != "done" :
341+ _LOGGER .error ("Problem issuing command: %s" , response ["msg" ])
342+ raise UnknownError
343+
300344 async def get_override (self ) -> None :
301345 """Get the manual override status."""
302346 url = f"{ self .url } override"
303347
304- if self ._user and self ._pwd :
305- auth = aiohttp .BasicAuth (self ._user , self ._pwd )
306-
307348 _LOGGER .debug ("Geting data from %s" , url )
308- async with aiohttp .ClientSession () as session :
309- async with session .get (url , auth = auth ) as resp :
310- if resp .status == 400 :
311- _LOGGER .debug ("JSON error: %s" , await resp .text ())
312- raise ParseJSONError
313- if resp .status == 401 :
314- _LOGGER .debug ("Authentication error: %s" , await resp .text ())
315- raise AuthenticationError
316- if resp .status == 404 :
317- error = await resp .json ()
318- _LOGGER .error ("Error getting override status: %s" , error ["msg" ])
319-
320- value = await resp .json ()
321- return value
349+ response = await self .process_request (url = url , method = "get" )
350+ return response
322351
323352 async def set_override (
324353 self ,
@@ -332,9 +361,6 @@ async def set_override(
332361 """Set the manual override status."""
333362 url = f"{ self .url } override"
334363
335- if self ._user and self ._pwd :
336- auth = aiohttp .BasicAuth (self ._user , self ._pwd )
337-
338364 if state not in ["active" , "disabled" ]:
339365 raise ValueError
340366
@@ -348,56 +374,26 @@ async def set_override(
348374 }
349375
350376 _LOGGER .debug ("Setting override config on %s" , url )
351- async with aiohttp .ClientSession () as session :
352- async with session .post (url , data = data , auth = auth ) as resp :
353- if resp .status == 400 :
354- _LOGGER .debug ("JSON error: %s" , await resp .text ())
355- raise ParseJSONError
356- if resp .status == 401 :
357- _LOGGER .debug ("Authentication error: %s" , await resp .text ())
358- raise AuthenticationError
359-
360- value = await resp .json ()
361- _LOGGER .debug ("Override set response: %s" , value ["msg" ])
362- return value
377+ response = await self .process_request (
378+ url = url , method = "post" , data = data
379+ ) # noqa: E501
380+ return response
363381
364382 async def toggle_override (self ) -> None :
365383 """Toggle the manual override status."""
366384 url = f"{ self .url } override"
367385
368- if self ._user and self ._pwd :
369- auth = aiohttp .BasicAuth (self ._user , self ._pwd )
370-
371386 _LOGGER .debug ("Toggling manual override %s" , url )
372- async with aiohttp .ClientSession () as session :
373- async with session .patch (url , auth = auth ) as resp :
374- if resp .status == 400 :
375- _LOGGER .debug ("JSON error: %s" , await resp .text ())
376- raise ParseJSONError
377- if resp .status == 401 :
378- _LOGGER .debug ("Authentication error: %s" , await resp .text ())
379- raise AuthenticationError
380-
381- _LOGGER .debug ("Toggle response: %s" , resp .status )
387+ response = await self .process_request (url = url , method = "patch" )
388+ _LOGGER .debug ("Toggle response: %s" , response ["msg" ])
382389
383390 async def clear_override (self ) -> None :
384391 """Clear the manual override status."""
385392 url = f"{ self .url } overrride"
386393
387- if self ._user and self ._pwd :
388- auth = aiohttp .BasicAuth (self ._user , self ._pwd )
389-
390394 _LOGGER .debug ("Clearing manual overrride %s" , url )
391- async with aiohttp .ClientSession () as session :
392- async with session .delete (url , auth = auth ) as resp :
393- if resp .status == 400 :
394- _LOGGER .debug ("JSON error: %s" , await resp .text ())
395- raise ParseJSONError
396- if resp .status == 401 :
397- _LOGGER .debug ("Authentication error: %s" , await resp .text ())
398- raise AuthenticationError
399-
400- _LOGGER .debug ("Toggle response: %s" , resp .status )
395+ response = await self .process_request (url = url , method = "delete" )
396+ _LOGGER .debug ("Toggle response: %s" , response ["msg" ])
401397
402398 @property
403399 def hostname (self ) -> str :
0 commit comments