Skip to content

Commit a36d6d6

Browse files
committed
Add batch reading functionality
1 parent eac780a commit a36d6d6

File tree

5 files changed

+51
-22
lines changed

5 files changed

+51
-22
lines changed

custom_components/solis_cloud_control/api.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
API_BASE_URL,
1313
API_CONCURRENT_REQUESTS,
1414
API_CONTROL_ENDPOINT,
15+
API_READ_BATCH_ENDPOINT,
1516
API_READ_ENDPOINT,
1617
API_RETRY_COUNT,
1718
API_RETRY_DELAY_SECONDS,
@@ -121,6 +122,43 @@ async def read(self, cid: int) -> str:
121122

122123
return data["msg"]
123124

125+
@backoff.on_exception(
126+
backoff.constant,
127+
SolisCloudControlApiError,
128+
max_tries=API_RETRY_COUNT,
129+
interval=API_RETRY_DELAY_SECONDS,
130+
logger=_LOGGER,
131+
)
132+
async def at_read_batch(self, cids: list[int]) -> dict[int, str]:
133+
date = current_date()
134+
payload = {"inverterSn": self._inverter_sn, "cids": ",".join(map(str, cids))}
135+
136+
data = await self._request(date, API_READ_BATCH_ENDPOINT, payload)
137+
138+
if data is None:
139+
raise SolisCloudControlApiError("ReadBatch failed: 'data' field is missing in response")
140+
141+
if not isinstance(data, list):
142+
raise SolisCloudControlApiError("ReadBatch failed: response data is not an array")
143+
144+
result = {}
145+
for outer_item in data:
146+
if not isinstance(outer_item, list):
147+
continue
148+
149+
for item in outer_item:
150+
if not isinstance(item, dict):
151+
continue
152+
153+
if "msg" not in item:
154+
raise SolisCloudControlApiError("ReadBatch failed: 'msg' field is missing in response item")
155+
if "cid" not in item:
156+
raise SolisCloudControlApiError("ReadBatch failed: 'cid' field is missing in response item")
157+
158+
result[int(item["cid"])] = item["msg"]
159+
160+
return result
161+
124162
@backoff.on_exception(
125163
backoff.constant,
126164
SolisCloudControlApiError,

custom_components/solis_cloud_control/config_flow.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ async def async_step_user(self, user_input: dict[str, any] | None = None) -> Con
4444
_LOGGER.exception(error)
4545
errors["base"] = "unknown_error"
4646
else:
47-
await self.async_set_unique_id(unique_id=user_input[CONF_INVERTER_SN])
47+
await self.async_set_unique_id(unique_id=user_input[CONF_API_KEY])
4848
self._abort_if_unique_id_configured()
4949
return self.async_create_entry(
5050
title=user_input[CONF_API_KEY],

custom_components/solis_cloud_control/const.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
API_BASE_URL = "https://www.soliscloud.com:13333"
66
API_READ_ENDPOINT = "/v2/api/atRead"
7+
API_READ_BATCH_ENDPOINT = "/v2/api/atReadBatch"
78
API_CONTROL_ENDPOINT = "/v2/api/control"
89
API_TIMEOUT_SECONDS = 10
910
API_RETRY_COUNT = 3 # initial attempt + 2 retries

custom_components/solis_cloud_control/coordinator.py

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
from homeassistant.config_entries import ConfigEntry
66
from homeassistant.core import HomeAssistant
7-
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
7+
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
88

99
from custom_components.solis_cloud_control.api import SolisCloudControlApiClient, SolisCloudControlApiError
1010
from custom_components.solis_cloud_control.const import (
@@ -53,20 +53,10 @@ def __init__(
5353
self.api_client = api_client
5454

5555
async def _async_update_data(self) -> SolisCloudControlData:
56-
data = SolisCloudControlData()
57-
58-
async def fetch_cid_value(cid: int) -> tuple[int, str | None]:
59-
try:
60-
value = await self.api_client.read(cid)
61-
return cid, value
62-
except SolisCloudControlApiError as error:
63-
_LOGGER.error("Failed to read CID %s: %s", cid, error)
64-
return cid, None
65-
66-
tasks = [fetch_cid_value(cid) for cid in _ALL_CIDS]
67-
results = await asyncio.gather(*tasks)
68-
69-
for cid, value in results:
70-
data[cid] = value
71-
72-
return data
56+
try:
57+
result = await self.api_client.at_read_batch(_ALL_CIDS)
58+
data = SolisCloudControlData({cid: result.get(cid) for cid in _ALL_CIDS})
59+
_LOGGER.debug("Data read from API: %s", data)
60+
return data
61+
except SolisCloudControlApiError as error:
62+
raise UpdateFailed(error) from error

custom_components/solis_cloud_control/translations/en.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,18 @@
66
"data": {
77
"api_key": "API key",
88
"token": "API token",
9-
"inverter_sn": "Inverter serial number",
9+
"inverter_sn": "Inverter serial number"
1010
}
1111
}
1212
},
1313
"error": {
1414
"invalid_auth": "Invalid API key or token",
1515
"invalid_inverter_sn": "Invalid inverter serial number",
1616
"connection_error": "Connection error",
17-
"unknown_error": "Unknown error",
17+
"unknown_error": "Unknown error"
1818
},
1919
"abort": {
20-
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]"
20+
"already_configured": "This entry is already configured."
2121
}
2222
}
2323
}

0 commit comments

Comments
 (0)