1
1
import asyncio
2
2
import json
3
3
import logging
4
- from datetime import datetime
5
4
6
5
import aiohttp
7
6
@@ -52,11 +51,33 @@ def __init__(
52
51
self ._session = session
53
52
self ._request_semaphore = asyncio .Semaphore (API_CONCURRENT_REQUESTS )
54
53
55
- async def _request (self , date : datetime , endpoint : str , payload : dict [str , any ] = None ) -> dict [str , any ] | None :
54
+ async def _execute_request_with_retry (
55
+ self ,
56
+ endpoint : str ,
57
+ payload : dict [str , any ],
58
+ retry_count : int = API_RETRY_COUNT ,
59
+ retry_delay : float = API_RETRY_DELAY_SECONDS ,
60
+ ) -> any :
61
+ attempt = 0
62
+
63
+ while attempt < retry_count :
64
+ try :
65
+ return await self ._execute_request (endpoint , payload )
66
+ except SolisCloudControlApiError as err :
67
+ attempt += 1
68
+ if attempt < retry_count :
69
+ _LOGGER .warning ("Retrying due to error: %s (attempt %d/%d)" , str (err ), attempt , retry_count )
70
+ await asyncio .sleep (retry_delay )
71
+ else :
72
+ raise
73
+
74
+ async def _execute_request (self , endpoint : str , payload : dict [str , any ] = None ) -> any :
56
75
body = json .dumps (payload )
57
76
58
77
payload_digest = digest (body )
59
78
content_type = "application/json"
79
+
80
+ date = current_date ()
60
81
date_formatted = format_date (date )
61
82
62
83
authorization_str = "\n " .join (["POST" , payload_digest , content_type , date_formatted , endpoint ])
@@ -77,8 +98,8 @@ async def _request(self, date: datetime, endpoint: str, payload: dict[str, any]
77
98
_LOGGER .debug ("API request '%s': %s" , endpoint , json .dumps (payload , indent = 2 ))
78
99
79
100
try :
80
- async with self . _request_semaphore :
81
- async with asyncio . timeout ( API_TIMEOUT_SECONDS ) :
101
+ async with asyncio . timeout ( API_TIMEOUT_SECONDS ) :
102
+ async with self . _request_semaphore :
82
103
async with self ._session .post (url , headers = headers , json = payload ) as response :
83
104
if response .status != 200 :
84
105
error_text = await response .text ()
@@ -100,13 +121,9 @@ async def _request(self, date: datetime, endpoint: str, payload: dict[str, any]
100
121
raise SolisCloudControlApiError (f"Error accessing { url } : { str (err )} " ) from err
101
122
102
123
async def read (self , inverter_sn : str , cid : int ) -> str :
103
- date = current_date ()
104
124
payload = {"inverterSn" : inverter_sn , "cid" : cid }
105
125
106
- async def request () -> str :
107
- return await self ._request (date , API_READ_ENDPOINT , payload )
108
-
109
- data = await _retry_request (request )
126
+ data = await self ._execute_request_with_retry (API_READ_ENDPOINT , payload )
110
127
111
128
if data is None :
112
129
raise SolisCloudControlApiError ("Read failed: 'data' field is missing in response" )
@@ -117,13 +134,9 @@ async def request() -> str:
117
134
return data ["msg" ]
118
135
119
136
async def read_batch (self , inverter_sn : str , cids : list [int ]) -> dict [int , str ]:
120
- date = current_date ()
121
137
payload = {"inverterSn" : inverter_sn , "cids" : "," .join (map (str , cids ))}
122
138
123
- async def request () -> dict [str , any ]:
124
- return await self ._request (date , API_READ_BATCH_ENDPOINT , payload )
125
-
126
- data = await _retry_request (request )
139
+ data = await self ._execute_request_with_retry (API_READ_BATCH_ENDPOINT , payload )
127
140
128
141
if data is None :
129
142
raise SolisCloudControlApiError ("ReadBatch failed: 'data' field is missing in response" )
@@ -150,15 +163,11 @@ async def request() -> dict[str, any]:
150
163
return result
151
164
152
165
async def control (self , inverter_sn : str , cid : int , value : str , old_value : str | None = None ) -> None :
153
- date = current_date ()
154
166
payload = {"inverterSn" : inverter_sn , "cid" : cid , "value" : value }
155
167
if old_value is not None :
156
168
payload ["yuanzhi" ] = old_value
157
169
158
- async def request () -> None :
159
- return await self ._request (date , API_CONTROL_ENDPOINT , payload )
160
-
161
- data_array = _retry_request (request )
170
+ data_array = await self ._execute_request_with_retry (API_CONTROL_ENDPOINT , payload )
162
171
163
172
if data_array is None :
164
173
return
@@ -172,17 +181,3 @@ async def request() -> None:
172
181
raise SolisCloudControlApiError (f"Control failed: { error_msg } " , response_code = str (code ))
173
182
174
183
return
175
-
176
-
177
- async def _retry_request (request : callable ) -> any :
178
- attempt = 0
179
- while attempt < API_RETRY_COUNT :
180
- try :
181
- return await request ()
182
- except SolisCloudControlApiError as err :
183
- attempt += 1
184
- if attempt < API_RETRY_COUNT :
185
- _LOGGER .warning ("Retrying due to error: %s (attempt %d/%d)" , str (err ), attempt , API_RETRY_COUNT )
186
- await asyncio .sleep (API_RETRY_DELAY_SECONDS )
187
- else :
188
- raise
0 commit comments