1.8.1
This commit is contained in:
parent
2afab331db
commit
b41590e888
180
api/api.py
180
api/api.py
|
@ -149,11 +149,11 @@ _API_ENDPOINTS = {
|
|||
"compatible_process": "power_service/v1/app/compatible/get_compatible_process", # contains solar_info plus OTA processing codes, works only with owner account
|
||||
"get_device_fittings": "power_service/v1/app/get_relate_device_fittings", # Device fittings for given site id and device sn. Shows Accessories like Solarbank 0W Switch info
|
||||
"energy_analysis": "power_service/v1/site/energy_analysis", # Fetch energy data for given time frames
|
||||
"home_load_chart": "power_service/v1/site/get_home_load_chart", # Fetch data as displayed in home load chart for given site_id and optional device SN (empty if solarbank not connected)
|
||||
"home_load_chart": "power_service/v1/site/get_home_load_chart", # Fetch data as displayed in home load chart for schedule adjustments for given site_id and optional device SN (empty if solarbank not connected)
|
||||
"get_upgrade_record": "power_service/v1/app/get_upgrade_record", # get list of firmware update history
|
||||
"check_upgrade_record": "power_service/v1/app/check_upgrade_record", # show an upgrade record for the device, types 1-3 show different info, only works for owner account
|
||||
"get_message_unread": "power_service/v1/get_message_unread", # GET method to show if there are unread messages for account
|
||||
"get_message": "power_service/v1/get_message", # get list of max Messages from certain time, last_time format unknown
|
||||
"get_upgrade_record": "power_service/v1/app/get_upgrade_record", # get list of firmware update history
|
||||
"get_mqtt_info": "app/devicemanage/get_user_mqtt_info", # get mqtt server and certificates, not explored or used
|
||||
}
|
||||
|
||||
|
@ -184,7 +184,7 @@ _API_ENDPOINTS = {
|
|||
'power_service/v1/app/share_site/delete_inviting_member',
|
||||
'power_service/v1/app/share_site/get_invited_list',
|
||||
'power_service/v1/app/share_site/join_site',
|
||||
'power_service/v1/app/upgrade_event_report',
|
||||
'power_service/v1/app/upgrade_event_report', # post an entry to upgrade event report
|
||||
'power_service/v1/app/get_phonecode_list',
|
||||
'power_service/v1/get_message_not_disturb', # get do not disturb messages settings
|
||||
'power_service/v1/message_not_disturb', # change do not disurb messages settings
|
||||
|
@ -410,7 +410,9 @@ class RequestCounter:
|
|||
# limit the counter entries to 1 hour when adding new
|
||||
self.recycle()
|
||||
|
||||
def recycle(self, last_time: datetime = datetime.now() - timedelta(hours=1)) -> None:
|
||||
def recycle(
|
||||
self, last_time: datetime = datetime.now() - timedelta(hours=1)
|
||||
) -> None:
|
||||
"""Remove oldest timestamps from beginning of counter until last_time is reached, default is 1 hour ago."""
|
||||
self.elements = [x for x in self.elements if x > last_time]
|
||||
|
||||
|
@ -584,7 +586,7 @@ class AnkerSolixApi:
|
|||
self._logger.error(err)
|
||||
return {}
|
||||
|
||||
def _saveToFile(self, filename: str, data: dict = None) -> bool:
|
||||
def _saveToFile(self, filename: str, data: dict | None = None) -> bool:
|
||||
"""Save json data to given file for testing."""
|
||||
if self.mask_credentials:
|
||||
masked_filename = filename.replace(
|
||||
|
@ -625,9 +627,9 @@ class AnkerSolixApi:
|
|||
def _update_dev( # noqa: C901
|
||||
self,
|
||||
devData: dict,
|
||||
devType: str = None,
|
||||
siteId: str = None,
|
||||
isAdmin: bool = None,
|
||||
devType: str | None = None,
|
||||
siteId: str | None = None,
|
||||
isAdmin: bool | None = None,
|
||||
) -> str | None:
|
||||
"""Update the internal device details dictionary with the given data. The device_sn key must be set in the data dict for the update to be applied.
|
||||
|
||||
|
@ -858,7 +860,7 @@ class AnkerSolixApi:
|
|||
self.devices.update({str(sn): device})
|
||||
return sn
|
||||
|
||||
def testDir(self, subfolder: str = None) -> str:
|
||||
def testDir(self, subfolder: str | None = None) -> str:
|
||||
"""Get or set the subfolder for local API test files."""
|
||||
if not subfolder or subfolder == self._testdir:
|
||||
return self._testdir
|
||||
|
@ -869,35 +871,39 @@ class AnkerSolixApi:
|
|||
self._logger.info("Set Api test folder to: %s", subfolder)
|
||||
return self._testdir
|
||||
|
||||
def logLevel(self, level: int = None) -> int:
|
||||
def logLevel(self, level: int | None = None) -> int:
|
||||
"""Get or set the logger log level."""
|
||||
if level is not None and isinstance(level, int):
|
||||
self._logger.setLevel(level)
|
||||
self._logger.info("Set log level to: %s", level)
|
||||
return self._logger.getEffectiveLevel()
|
||||
|
||||
def requestDelay(self, delay: float = None) -> float:
|
||||
def requestDelay(self, delay: float | None = None) -> float:
|
||||
"""Get or set the api request delay in seconds."""
|
||||
if (
|
||||
delay is not None
|
||||
and isinstance(delay, (float,int))
|
||||
and delay != self._request_delay
|
||||
and isinstance(delay, (float, int))
|
||||
and float(delay) != float(self._request_delay)
|
||||
):
|
||||
self._request_delay = min(
|
||||
SolixDefaults.REQUEST_DELAY_MAX,
|
||||
max(SolixDefaults.REQUEST_DELAY_MIN, delay),
|
||||
self._request_delay = float(
|
||||
min(
|
||||
SolixDefaults.REQUEST_DELAY_MAX,
|
||||
max(SolixDefaults.REQUEST_DELAY_MIN, delay),
|
||||
)
|
||||
)
|
||||
self._logger.info(
|
||||
"Set api request delay to %.3f seconds", self._request_delay
|
||||
)
|
||||
return self._request_delay
|
||||
|
||||
async def _wait_delay(self, delay: float = None) -> None:
|
||||
async def _wait_delay(self, delay: float | None = None) -> None:
|
||||
"""Wait at least for the defined Api request delay or for the provided delay in seconds since the last request occured."""
|
||||
if delay is not None and isinstance(delay, (float,int)):
|
||||
delay = min(
|
||||
SolixDefaults.REQUEST_DELAY_MAX,
|
||||
max(SolixDefaults.REQUEST_DELAY_MIN, delay),
|
||||
if delay is not None and isinstance(delay, (float, int)):
|
||||
delay = float(
|
||||
min(
|
||||
SolixDefaults.REQUEST_DELAY_MAX,
|
||||
max(SolixDefaults.REQUEST_DELAY_MIN, delay),
|
||||
)
|
||||
)
|
||||
else:
|
||||
delay = self._request_delay
|
||||
|
@ -934,15 +940,13 @@ class AnkerSolixApi:
|
|||
"%s",
|
||||
self.mask_values(data, "user_id", "auth_token", "email", "geo_key"),
|
||||
)
|
||||
self._retry_attempt = (
|
||||
False # clear retry attempt to allow retry for authentication refresh
|
||||
)
|
||||
# clear retry attempt to allow retry for authentication refresh
|
||||
self._retry_attempt = False
|
||||
else:
|
||||
self._logger.debug("Fetching new Login credentials from server")
|
||||
now = datetime.now().astimezone()
|
||||
self._retry_attempt = (
|
||||
True # set retry attempt to avoid retry on failed authentication
|
||||
)
|
||||
# set retry attempt to avoid retry on failed authentication
|
||||
self._retry_attempt = True
|
||||
auth_resp = await self.request(
|
||||
"post",
|
||||
_API_LOGIN,
|
||||
|
@ -1089,7 +1093,7 @@ class AnkerSolixApi:
|
|||
# get first the body text for usage in error detail logging if necessary
|
||||
body_text = await resp.text()
|
||||
data = {}
|
||||
resp.raise_for_status() # any response status >= 400
|
||||
resp.raise_for_status() # any response status >= 400
|
||||
if (data := await resp.json(content_type=None)) and self.encrypt_body:
|
||||
# TODO(#70): Test and Support optional encryption for body
|
||||
# data dict has to be decoded when encrypted
|
||||
|
@ -1109,43 +1113,50 @@ class AnkerSolixApi:
|
|||
)
|
||||
else:
|
||||
self._logger.debug("Response Data: %s", data)
|
||||
self._retry_attempt = False # reset retry flag only when valid token received and not another login request
|
||||
# reset retry flag only when valid token received and not another login request
|
||||
self._retry_attempt = False
|
||||
|
||||
errors.raise_error(data) # check the Api response status code in the data
|
||||
# check the Api response status code in the data
|
||||
errors.raise_error(data)
|
||||
|
||||
# valid response at this point, mark login and return data
|
||||
self._loggedIn = True
|
||||
return data # noqa: TRY300
|
||||
|
||||
except (
|
||||
ClientError
|
||||
) as err: # Exception from ClientSession based on standard response status codes
|
||||
# Exception from ClientSession based on standard response status codes
|
||||
except ClientError as err:
|
||||
self._logger.error("Api Request Error: %s", err)
|
||||
self._logger.error("Response Text: %s", body_text)
|
||||
# Prepare data dict for Api error lookup
|
||||
if not data:
|
||||
data = {}
|
||||
if not hasattr(data,"code"):
|
||||
if not hasattr(data, "code"):
|
||||
data["code"] = resp.status
|
||||
if not hasattr(data,"msg"):
|
||||
if not hasattr(data, "msg"):
|
||||
data["msg"] = body_text
|
||||
if resp.status in [401,403]:
|
||||
if resp.status in [401, 403]:
|
||||
# Unauthorized or forbidden request
|
||||
if self._retry_attempt:
|
||||
errors.raise_error(data, prefix=f"Login failed for user {self._email}")
|
||||
# catch error if Api code not defined
|
||||
raise errors.AuthorizationError(
|
||||
f"Login failed for user {self._email}"
|
||||
) from err
|
||||
self._logger.warning("Login failed, retrying authentication")
|
||||
if await self.async_authenticate(restart=True):
|
||||
return await self.request(
|
||||
method, endpoint, headers=headers, json=json
|
||||
)
|
||||
self._logger.error("Re-Login failed for user %s", self._email)
|
||||
elif resp.status in [429]:
|
||||
# reattempt autentication with same credentials if cached token was kicked out
|
||||
# retry attempt is set if login response data were not cached to fail immediately
|
||||
if not self._retry_attempt:
|
||||
self._logger.warning("Login failed, retrying authentication")
|
||||
if await self.async_authenticate(restart=True):
|
||||
return await self.request(
|
||||
method, endpoint, headers=headers, json=json
|
||||
)
|
||||
self._logger.error("Re-Login failed for user %s", self._email)
|
||||
errors.raise_error(
|
||||
data, prefix=f"Login failed for user {self._email}"
|
||||
)
|
||||
# catch error if Api code not defined
|
||||
raise errors.AuthorizationError(
|
||||
f"Login failed for user {self._email}"
|
||||
) from err
|
||||
if resp.status in [429]:
|
||||
# Too Many Requests, add stats to message
|
||||
errors.raise_error(data, prefix=f"Too Many Requests: {self.request_count}")
|
||||
errors.raise_error(
|
||||
data, prefix=f"Too Many Requests: {self.request_count}"
|
||||
)
|
||||
else:
|
||||
# raise Anker Solix error if code is known
|
||||
errors.raise_error(data)
|
||||
|
@ -1349,7 +1360,7 @@ class AnkerSolixApi:
|
|||
return self.sites
|
||||
|
||||
async def update_site_details(
|
||||
self, fromFile: bool = False, exclude: set = None
|
||||
self, fromFile: bool = False, exclude: set | None = None
|
||||
) -> dict:
|
||||
"""Get the latest updates for additional site related details updated less frequently.
|
||||
|
||||
|
@ -1374,7 +1385,7 @@ class AnkerSolixApi:
|
|||
return self.sites
|
||||
|
||||
async def update_device_details(
|
||||
self, fromFile: bool = False, exclude: set = None
|
||||
self, fromFile: bool = False, exclude: set | None = None
|
||||
) -> dict:
|
||||
"""Get the latest updates for additional device info updated less frequently.
|
||||
|
||||
|
@ -1455,7 +1466,7 @@ class AnkerSolixApi:
|
|||
|
||||
return self.devices
|
||||
|
||||
async def update_device_energy(self, exclude: set = None) -> dict:
|
||||
async def update_device_energy(self, exclude: set | None = None) -> dict:
|
||||
"""Get the energy statistics for given device types from today and yesterday.
|
||||
|
||||
Yesterday energy will be queried only once if not available yet, but not updated in subsequent refreshes.
|
||||
|
@ -1850,7 +1861,11 @@ class AnkerSolixApi:
|
|||
return data
|
||||
|
||||
async def set_site_price(
|
||||
self, siteId: str, price: float = None, unit: str = None, co2: float = None
|
||||
self,
|
||||
siteId: str,
|
||||
price: float | None = None,
|
||||
unit: str | None = None,
|
||||
co2: float | None = None,
|
||||
) -> bool:
|
||||
"""Set the power price, the unit and/or CO2 for a site.
|
||||
|
||||
|
@ -1984,7 +1999,7 @@ class AnkerSolixApi:
|
|||
self,
|
||||
siteId: str,
|
||||
paramType: str = SolixParmType.SOLARBANK_SCHEDULE.value,
|
||||
deviceSn: str = None,
|
||||
deviceSn: str | None = None,
|
||||
fromFile: bool = False,
|
||||
) -> dict:
|
||||
r"""Get device parameters (e.g. solarbank schedule). This can be queried for each siteId listed in the homepage info site_list. The paramType is always 4, but can be modified if necessary.
|
||||
|
@ -2040,7 +2055,7 @@ class AnkerSolixApi:
|
|||
paramData: dict,
|
||||
paramType: str = SolixParmType.SOLARBANK_SCHEDULE.value,
|
||||
command: int = 17,
|
||||
deviceSn: str = None,
|
||||
deviceSn: str | None = None,
|
||||
) -> dict:
|
||||
"""Set device parameters (e.g. solarbank schedule).
|
||||
|
||||
|
@ -2073,9 +2088,9 @@ class AnkerSolixApi:
|
|||
siteId: str,
|
||||
deviceSn: str,
|
||||
all_day: bool = False,
|
||||
preset: int = None,
|
||||
export: bool = None,
|
||||
charge_prio: int = None,
|
||||
preset: int | None = None,
|
||||
export: bool | None = None,
|
||||
charge_prio: int | None = None,
|
||||
set_slot: SolarbankTimeslot = None,
|
||||
insert_slot: SolarbankTimeslot = None,
|
||||
) -> bool:
|
||||
|
@ -2611,10 +2626,10 @@ class AnkerSolixApi:
|
|||
)
|
||||
return resp.get("data", {})
|
||||
|
||||
async def get_upgrade_record(
|
||||
async def check_upgrade_record(
|
||||
self, recordType: int = 2, fromFile: bool = False
|
||||
) -> dict:
|
||||
"""Get upgrade record, shows device updates with their last version. Type 0-3 work.
|
||||
"""Check upgrade record, shows device updates with their last version. Type 0-3 work.
|
||||
|
||||
Example data:
|
||||
{"is_record": true,"device_list": [{
|
||||
|
@ -2624,7 +2639,7 @@ class AnkerSolixApi:
|
|||
data = {"type": recordType}
|
||||
if fromFile:
|
||||
resp = self._loadFromFile(
|
||||
os.path.join(self._testdir, f"upgrade_record_{recordType}.json")
|
||||
os.path.join(self._testdir, f"check_upgrade_record_{recordType}.json")
|
||||
)
|
||||
else:
|
||||
resp = await self.request(
|
||||
|
@ -2632,14 +2647,45 @@ class AnkerSolixApi:
|
|||
)
|
||||
return resp.get("data", {})
|
||||
|
||||
async def get_upgrade_record(
|
||||
self, deviceSn: str | None = None, siteId: str | None = None, recordType: int | None = None, fromFile: bool = False
|
||||
) -> dict:
|
||||
"""Get upgrade record for a device serial or site ID, shows update history. Type 1 works for solarbank, type 2 for site ID.
|
||||
|
||||
Example data:
|
||||
{"device_sn": "9JVB42LJK8J0P5RY", "site_id": "", "upgrade_record_list": [
|
||||
{"upgrade_time": "2024-02-29 12:38:23","upgrade_version": "v1.5.6","pre_version": "v1.4.4","upgrade_type": "1","upgrade_desc": "",
|
||||
"device_sn": "9JVB42LJK8J0P5RY","device_name": "9JVB42LJK8J0P5RY","child_upgrade_records": null},
|
||||
{"upgrade_time": "2023-12-29 10:23:06","upgrade_version": "v1.4.4","pre_version": "v0.0.6.6","upgrade_type": "1","upgrade_desc": "",
|
||||
"device_sn": "9JVB42LJK8J0P5RY","device_name": "9JVB42LJK8J0P5RY","child_upgrade_records": null},
|
||||
{"upgrade_time": "2023-11-02 13:43:09","upgrade_version": "v1.4.1","pre_version": "v0.0.6.5","upgrade_type": "1","upgrade_desc": "",
|
||||
"device_sn": "9JVB42LJK8J0P5RY","device_name": "9JVB42LJK8J0P5RY","child_upgrade_records": null}]},
|
||||
"""
|
||||
if deviceSn:
|
||||
data = {"device_sn": deviceSn, "type": 1 if recordType is None else recordType}
|
||||
elif siteId:
|
||||
data = {"site_id": siteId, "type": 2 if recordType is None else recordType}
|
||||
else:
|
||||
recordType = 0 if recordType is None else recordType
|
||||
data = {"type": recordType}
|
||||
if fromFile:
|
||||
resp = self._loadFromFile(
|
||||
os.path.join(self._testdir, f"get_upgrade_record_{deviceSn if deviceSn else siteId if siteId else recordType}.json")
|
||||
)
|
||||
else:
|
||||
resp = await self.request(
|
||||
"post", _API_ENDPOINTS["get_upgrade_record"], json=data
|
||||
)
|
||||
return resp.get("data", {})
|
||||
|
||||
async def energy_analysis(
|
||||
self,
|
||||
siteId: str,
|
||||
deviceSn: str,
|
||||
rangeType: str = None,
|
||||
startDay: datetime = None,
|
||||
endDay: datetime = None,
|
||||
devType: str = None,
|
||||
rangeType: str | None = None,
|
||||
startDay: datetime | None = None,
|
||||
endDay: datetime | None = None,
|
||||
devType: str | None = None,
|
||||
) -> dict:
|
||||
"""Fetch Energy data for given device and optional time frame.
|
||||
|
||||
|
@ -2770,7 +2816,7 @@ class AnkerSolixApi:
|
|||
table.update({daystr: entry})
|
||||
return table
|
||||
|
||||
async def home_load_chart(self, siteId: str, deviceSn: str = None) -> dict:
|
||||
async def home_load_chart(self, siteId: str, deviceSn: str | None = None) -> dict:
|
||||
"""Get home load chart data.
|
||||
|
||||
Example data:
|
||||
|
|
|
@ -75,6 +75,8 @@ ERRORS: dict[int, type[AnkerSolixError]] = {
|
|||
401: AuthorizationError,
|
||||
403: AuthorizationError,
|
||||
429: RequestLimitError,
|
||||
502: ConnectError,
|
||||
504: ConnectError,
|
||||
997: ConnectError,
|
||||
998: NetworkError,
|
||||
999: ServerError,
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
{
|
||||
"DILM86K2GJV2NRAI": {
|
||||
"device_sn": "DILM86K2GJV2NRAI",
|
||||
"G55HAP9LVQO2LAPM": {
|
||||
"device_sn": "G55HAP9LVQO2LAPM",
|
||||
"type": "solarbank",
|
||||
"site_id": "bdd7d770-bcb7-d22b-cafc-d0b2eddc4e23",
|
||||
"site_id": "9e40dc42-adac-7fba-dead-a1bba7bff34e",
|
||||
"is_admin": true,
|
||||
"device_pn": "A17C0",
|
||||
"battery_soc": "6",
|
||||
"battery_soc": "17",
|
||||
"battery_capacity": "1600",
|
||||
"battery_energy": "96",
|
||||
"charging_power": "64",
|
||||
"battery_energy": "272",
|
||||
"charging_power": "-190",
|
||||
"power_unit": "W",
|
||||
"charging_status": "3",
|
||||
"charging_status_desc": "charge_bypass",
|
||||
"charging_status": "2",
|
||||
"charging_status_desc": "discharge",
|
||||
"status": "1",
|
||||
"status_desc": "online",
|
||||
"wireless_type": "1",
|
||||
"input_power": "154",
|
||||
"output_power": "90",
|
||||
"set_output_power": "0",
|
||||
"input_power": "0",
|
||||
"output_power": "190",
|
||||
"set_output_power": "300",
|
||||
"power_cutoff": 5,
|
||||
"alias": "SB E1600",
|
||||
"set_system_output_power": "0",
|
||||
"bt_ble_mac": "3CEAAD9FDDF7",
|
||||
"set_system_output_power": "300",
|
||||
"bt_ble_mac": "FEDCEB33AA9A",
|
||||
"name": "Solarbank E1600",
|
||||
"wifi_online": true,
|
||||
"charge": false,
|
||||
|
@ -29,7 +29,7 @@
|
|||
"sw_version": "v1.5.6",
|
||||
"auto_upgrade": false,
|
||||
"wifi_name": "wifi-network-1",
|
||||
"wifi_signal": "54",
|
||||
"wifi_signal": "50",
|
||||
"power_cutoff_data": [
|
||||
{
|
||||
"id": 1,
|
||||
|
@ -49,7 +49,7 @@
|
|||
"solar_info": {
|
||||
"solar_brand": "ANKER",
|
||||
"solar_model": "A5143",
|
||||
"solar_sn": "9XK0FGWY2TWW",
|
||||
"solar_sn": "YTZL4ZEJ4R5B",
|
||||
"solar_model_name": "MI80 Microinverter(BLE)"
|
||||
},
|
||||
"schedule": {
|
||||
|
@ -57,7 +57,7 @@
|
|||
{
|
||||
"id": 0,
|
||||
"start_time": "00:00",
|
||||
"end_time": "06:30",
|
||||
"end_time": "07:20",
|
||||
"turn_on": true,
|
||||
"appliance_loads": [
|
||||
{
|
||||
|
@ -71,21 +71,21 @@
|
|||
"power_setting_mode": 1,
|
||||
"device_power_loads": [
|
||||
{
|
||||
"device_sn": "DILM86K2GJV2NRAI",
|
||||
"device_sn": "G55HAP9LVQO2LAPM",
|
||||
"power": 150
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 0,
|
||||
"start_time": "06:30",
|
||||
"end_time": "18:30",
|
||||
"start_time": "07:20",
|
||||
"end_time": "19:40",
|
||||
"turn_on": false,
|
||||
"appliance_loads": [
|
||||
{
|
||||
"id": 0,
|
||||
"name": "Benutzerdefiniert",
|
||||
"power": 100,
|
||||
"power": 140,
|
||||
"number": 1
|
||||
}
|
||||
],
|
||||
|
@ -93,14 +93,14 @@
|
|||
"power_setting_mode": 1,
|
||||
"device_power_loads": [
|
||||
{
|
||||
"device_sn": "DILM86K2GJV2NRAI",
|
||||
"power": 50
|
||||
"device_sn": "G55HAP9LVQO2LAPM",
|
||||
"power": 70
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 0,
|
||||
"start_time": "18:30",
|
||||
"start_time": "19:40",
|
||||
"end_time": "24:00",
|
||||
"turn_on": true,
|
||||
"appliance_loads": [
|
||||
|
@ -115,7 +115,7 @@
|
|||
"power_setting_mode": 1,
|
||||
"device_power_loads": [
|
||||
{
|
||||
"device_sn": "DILM86K2GJV2NRAI",
|
||||
"device_sn": "G55HAP9LVQO2LAPM",
|
||||
"power": 150
|
||||
}
|
||||
]
|
||||
|
@ -130,8 +130,8 @@
|
|||
"display_advanced_mode": 0,
|
||||
"advanced_mode_min_load": 0
|
||||
},
|
||||
"preset_system_output_power": 100,
|
||||
"preset_allow_export": false,
|
||||
"preset_system_output_power": 300,
|
||||
"preset_allow_export": true,
|
||||
"preset_charge_priority": 10,
|
||||
"fittings": {}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
{
|
||||
"bdd7d770-bcb7-d22b-cafc-d0b2eddc4e23": {
|
||||
"9e40dc42-adac-7fba-dead-a1bba7bff34e": {
|
||||
"type": "system",
|
||||
"site_info": {
|
||||
"site_id": "bdd7d770-bcb7-d22b-cafc-d0b2eddc4e23",
|
||||
"site_id": "9e40dc42-adac-7fba-dead-a1bba7bff34e",
|
||||
"site_name": "BKW",
|
||||
"site_img": "",
|
||||
"device_type_list": [
|
||||
|
@ -36,17 +36,17 @@
|
|||
"statistics": [
|
||||
{
|
||||
"type": "1",
|
||||
"total": "135.13",
|
||||
"total": "183.54",
|
||||
"unit": "kwh"
|
||||
},
|
||||
{
|
||||
"type": "2",
|
||||
"total": "134.72",
|
||||
"total": "182.99",
|
||||
"unit": "kg"
|
||||
},
|
||||
{
|
||||
"type": "3",
|
||||
"total": "44.59",
|
||||
"total": "60.57",
|
||||
"unit": "\u20ac"
|
||||
}
|
||||
],
|
||||
|
@ -55,40 +55,40 @@
|
|||
"solarbank_list": [
|
||||
{
|
||||
"device_pn": "A17C0",
|
||||
"device_sn": "DILM86K2GJV2NRAI",
|
||||
"device_sn": "G55HAP9LVQO2LAPM",
|
||||
"device_img": "https://public-aiot-fra-prod.s3.dualstack.eu-central-1.amazonaws.com/anker-power/public/product/anker-power/e9478c2d-e665-4d84-95d7-dd4844f82055/20230719-144818.png",
|
||||
"battery_power": "6",
|
||||
"battery_power": "17",
|
||||
"bind_site_status": "",
|
||||
"charging_power": "64",
|
||||
"charging_power": "-190",
|
||||
"power_unit": "W",
|
||||
"charging_status": "3",
|
||||
"charging_status": "2",
|
||||
"status": "1",
|
||||
"wireless_type": "1",
|
||||
"main_version": "",
|
||||
"photovoltaic_power": "154",
|
||||
"output_power": "90",
|
||||
"photovoltaic_power": "0",
|
||||
"output_power": "190",
|
||||
"create_time": 1695392386,
|
||||
"set_load_power": "0",
|
||||
"set_load_power": "300",
|
||||
"output_cutoff_data": 5,
|
||||
"is_display": true,
|
||||
"alias_name": "SB E1600",
|
||||
"current_home_load": "0"
|
||||
"current_home_load": "300"
|
||||
}
|
||||
],
|
||||
"total_charging_power": "64",
|
||||
"total_charging_power": "-190.0",
|
||||
"power_unit": "W",
|
||||
"charging_status": "0",
|
||||
"total_battery_power": "0.06",
|
||||
"updated_time": "2024-03-27 11:49:04",
|
||||
"total_photovoltaic_power": "154",
|
||||
"total_output_power": "90.00",
|
||||
"total_battery_power": "0.17",
|
||||
"updated_time": "2024-04-24 01:33:08",
|
||||
"total_photovoltaic_power": "0",
|
||||
"total_output_power": "190.00",
|
||||
"display_set_power": false,
|
||||
"is_display_data": true
|
||||
},
|
||||
"retain_load": "0W",
|
||||
"retain_load": "300W",
|
||||
"updated_time": "01-01-0001 00:00:00",
|
||||
"power_site_type": 2,
|
||||
"site_id": "bdd7d770-bcb7-d22b-cafc-d0b2eddc4e23",
|
||||
"site_id": "9e40dc42-adac-7fba-dead-a1bba7bff34e",
|
||||
"powerpanel_list": [],
|
||||
"site_details": {
|
||||
"has_unread_msg": false,
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
"main_switch": true,
|
||||
"device_list": [
|
||||
{
|
||||
"device_sn": "DILM86K2GJV2NRAI",
|
||||
"device_sn": "G55HAP9LVQO2LAPM",
|
||||
"device_name": "Solarbank E1600",
|
||||
"auto_upgrade": false,
|
||||
"alias_name": "SB E1600",
|
||||
|
@ -13,5 +13,5 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"trace_id": "145dab32b452d3db2a81ce9506ee4010"
|
||||
"trace_id": "c6f8bd0ae3dd9eb8b3dbd8c84d2afba5"
|
||||
}
|
|
@ -4,10 +4,10 @@
|
|||
"data": {
|
||||
"data": [
|
||||
{
|
||||
"device_sn": "DILM86K2GJV2NRAI",
|
||||
"device_sn": "G55HAP9LVQO2LAPM",
|
||||
"product_code": "A17C0",
|
||||
"bt_ble_id": "3C:EA:AD:9F:DD:F7",
|
||||
"bt_ble_mac": "3CEAAD9FDDF7",
|
||||
"bt_ble_id": "FE:DC:EB:33:AA:9A",
|
||||
"bt_ble_mac": "FEDCEB33AA9A",
|
||||
"device_name": "Solarbank E1600",
|
||||
"alias_name": "SB E1600",
|
||||
"img_url": "https://public-aiot-fra-prod.s3.dualstack.eu-central-1.amazonaws.com/anker-power/public/product/anker-power/e9478c2d-e665-4d84-95d7-dd4844f82055/20230719-144818.png",
|
||||
|
@ -26,5 +26,5 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"trace_id": "acff073fd7e842994b11373fd1d3449e"
|
||||
"trace_id": "8fed8fc1bba815a1efa844983cecef9e"
|
||||
}
|
|
@ -5,5 +5,5 @@
|
|||
"device_list": null,
|
||||
"guide_txt": ""
|
||||
},
|
||||
"trace_id": "c55301e2c5686c8d75bf494a91d804b6"
|
||||
"trace_id": "ded0b8ad19ffe254edcf876c633e4735"
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
"ota_complete_status": 2,
|
||||
"process_skip_type": 2,
|
||||
"solar_info": {
|
||||
"solar_sn": "9XK0FGWY2TWW",
|
||||
"solar_sn": "YTZL4ZEJ4R5B",
|
||||
"solar_brand": "ANKER",
|
||||
"solar_model": "A5143",
|
||||
"brand_id": "3a9930f5-74ef-4e41-a797-04e6b33d3f0f",
|
||||
|
@ -15,5 +15,5 @@
|
|||
"solar_model_name": "MI80 Microinverter(BLE)"
|
||||
}
|
||||
},
|
||||
"trace_id": "7dbfd7538ad24749c1abfcf0fd93de5f"
|
||||
"trace_id": "077b4ed2b6fccac0a9dfcf8e4fdd85a6"
|
||||
}
|
|
@ -4,5 +4,5 @@
|
|||
"data": {
|
||||
"data": []
|
||||
},
|
||||
"trace_id": "823ef9f8a8c4fbdbe7e4abd4232f79c4"
|
||||
"trace_id": "a433dc2acdb4187e340cff4d6bb60f3c"
|
||||
}
|
|
@ -2,11 +2,11 @@
|
|||
"code": 0,
|
||||
"msg": "success!",
|
||||
"data": {
|
||||
"site_id": "bdd7d770-bcb7-d22b-cafc-d0b2eddc4e23",
|
||||
"home_load_data": "{\"ranges\":[{\"id\":0,\"start_time\":\"00:00\",\"end_time\":\"06:30\",\"turn_on\":true,\"appliance_loads\":[{\"id\":0,\"name\":\"Benutzerdefiniert\",\"power\":300,\"number\":1}],\"charge_priority\":10,\"power_setting_mode\":1,\"device_power_loads\":[{\"device_sn\":\"DILM86K2GJV2NRAI\",\"power\":150}]},{\"id\":0,\"start_time\":\"06:30\",\"end_time\":\"18:30\",\"turn_on\":false,\"appliance_loads\":[{\"id\":0,\"name\":\"Benutzerdefiniert\",\"power\":100,\"number\":1}],\"charge_priority\":10,\"power_setting_mode\":1,\"device_power_loads\":[{\"device_sn\":\"DILM86K2GJV2NRAI\",\"power\":50}]},{\"id\":0,\"start_time\":\"18:30\",\"end_time\":\"24:00\",\"turn_on\":true,\"appliance_loads\":[{\"id\":0,\"name\":\"Benutzerdefiniert\",\"power\":300,\"number\":1}],\"charge_priority\":10,\"power_setting_mode\":1,\"device_power_loads\":[{\"device_sn\":\"DILM86K2GJV2NRAI\",\"power\":150}]}],\"min_load\":100,\"max_load\":800,\"step\":0,\"is_charge_priority\":1,\"default_charge_priority\":80,\"is_zero_output_tips\":0,\"display_advanced_mode\":0,\"advanced_mode_min_load\":0}",
|
||||
"current_home_load": "0W",
|
||||
"site_id": "9e40dc42-adac-7fba-dead-a1bba7bff34e",
|
||||
"home_load_data": "{\"ranges\":[{\"id\":0,\"start_time\":\"00:00\",\"end_time\":\"07:20\",\"turn_on\":true,\"appliance_loads\":[{\"id\":0,\"name\":\"Benutzerdefiniert\",\"power\":300,\"number\":1}],\"charge_priority\":10,\"power_setting_mode\":1,\"device_power_loads\":[{\"device_sn\":\"G55HAP9LVQO2LAPM\",\"power\":150}]},{\"id\":0,\"start_time\":\"07:20\",\"end_time\":\"19:40\",\"turn_on\":false,\"appliance_loads\":[{\"id\":0,\"name\":\"Benutzerdefiniert\",\"power\":140,\"number\":1}],\"charge_priority\":10,\"power_setting_mode\":1,\"device_power_loads\":[{\"device_sn\":\"G55HAP9LVQO2LAPM\",\"power\":70}]},{\"id\":0,\"start_time\":\"19:40\",\"end_time\":\"24:00\",\"turn_on\":true,\"appliance_loads\":[{\"id\":0,\"name\":\"Benutzerdefiniert\",\"power\":300,\"number\":1}],\"charge_priority\":10,\"power_setting_mode\":1,\"device_power_loads\":[{\"device_sn\":\"G55HAP9LVQO2LAPM\",\"power\":150}]}],\"min_load\":100,\"max_load\":800,\"step\":0,\"is_charge_priority\":1,\"default_charge_priority\":80,\"is_zero_output_tips\":0,\"display_advanced_mode\":0,\"advanced_mode_min_load\":0}",
|
||||
"current_home_load": "300W",
|
||||
"parallel_home_load": "",
|
||||
"parallel_display": false
|
||||
},
|
||||
"trace_id": "adbafcecd3cac7f6c9feda1bcbab7aea"
|
||||
"trace_id": "ece0447b2ec3c1520e8ca17c1a4ce63f"
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
"code": 0,
|
||||
"msg": "success!",
|
||||
"data": {
|
||||
"param_data": "{\"ranges\":[{\"id\":0,\"start_time\":\"00:00\",\"end_time\":\"06:30\",\"turn_on\":true,\"appliance_loads\":[{\"id\":0,\"name\":\"Benutzerdefiniert\",\"power\":300,\"number\":1}],\"charge_priority\":10,\"power_setting_mode\":1,\"device_power_loads\":[{\"device_sn\":\"DILM86K2GJV2NRAI\",\"power\":150}]},{\"id\":0,\"start_time\":\"06:30\",\"end_time\":\"18:30\",\"turn_on\":false,\"appliance_loads\":[{\"id\":0,\"name\":\"Benutzerdefiniert\",\"power\":100,\"number\":1}],\"charge_priority\":10,\"power_setting_mode\":1,\"device_power_loads\":[{\"device_sn\":\"DILM86K2GJV2NRAI\",\"power\":50}]},{\"id\":0,\"start_time\":\"18:30\",\"end_time\":\"24:00\",\"turn_on\":true,\"appliance_loads\":[{\"id\":0,\"name\":\"Benutzerdefiniert\",\"power\":300,\"number\":1}],\"charge_priority\":10,\"power_setting_mode\":1,\"device_power_loads\":[{\"device_sn\":\"DILM86K2GJV2NRAI\",\"power\":150}]}],\"min_load\":100,\"max_load\":800,\"step\":0,\"is_charge_priority\":1,\"default_charge_priority\":80,\"is_zero_output_tips\":0,\"display_advanced_mode\":0,\"advanced_mode_min_load\":0}"
|
||||
"param_data": "{\"ranges\":[{\"id\":0,\"start_time\":\"00:00\",\"end_time\":\"07:20\",\"turn_on\":true,\"appliance_loads\":[{\"id\":0,\"name\":\"Benutzerdefiniert\",\"power\":300,\"number\":1}],\"charge_priority\":10,\"power_setting_mode\":1,\"device_power_loads\":[{\"device_sn\":\"G55HAP9LVQO2LAPM\",\"power\":150}]},{\"id\":0,\"start_time\":\"07:20\",\"end_time\":\"19:40\",\"turn_on\":false,\"appliance_loads\":[{\"id\":0,\"name\":\"Benutzerdefiniert\",\"power\":140,\"number\":1}],\"charge_priority\":10,\"power_setting_mode\":1,\"device_power_loads\":[{\"device_sn\":\"G55HAP9LVQO2LAPM\",\"power\":70}]},{\"id\":0,\"start_time\":\"19:40\",\"end_time\":\"24:00\",\"turn_on\":true,\"appliance_loads\":[{\"id\":0,\"name\":\"Benutzerdefiniert\",\"power\":300,\"number\":1}],\"charge_priority\":10,\"power_setting_mode\":1,\"device_power_loads\":[{\"device_sn\":\"G55HAP9LVQO2LAPM\",\"power\":150}]}],\"min_load\":100,\"max_load\":800,\"step\":0,\"is_charge_priority\":1,\"default_charge_priority\":80,\"is_zero_output_tips\":0,\"display_advanced_mode\":0,\"advanced_mode_min_load\":0}"
|
||||
},
|
||||
"trace_id": "2b3a35dbdeede8bbff7fba8dfeb0a3ff"
|
||||
"trace_id": "87feb1cf10c4cb773ea4deb7f8eacb84"
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
"code": 0,
|
||||
"msg": "success!",
|
||||
"data": {
|
||||
"device_sn": "",
|
||||
"site_id": "9e40dc42-adac-7fba-dead-a1bba7bff34e",
|
||||
"upgrade_record_list": [
|
||||
{
|
||||
"upgrade_time": "2024-02-29 10:48:23",
|
||||
"upgrade_version": "v1.5.6",
|
||||
"pre_version": "v1.4.4",
|
||||
"upgrade_type": "1",
|
||||
"upgrade_desc": "",
|
||||
"device_sn": "G55HAP9LVQO2LAPM",
|
||||
"device_name": "G55HAP9LVQO2LAPM",
|
||||
"child_upgrade_records": null
|
||||
},
|
||||
{
|
||||
"upgrade_time": "2023-12-28 15:57:06",
|
||||
"upgrade_version": "v1.4.4",
|
||||
"pre_version": "v0.0.6.6",
|
||||
"upgrade_type": "1",
|
||||
"upgrade_desc": "",
|
||||
"device_sn": "G55HAP9LVQO2LAPM",
|
||||
"device_name": "G55HAP9LVQO2LAPM",
|
||||
"child_upgrade_records": null
|
||||
},
|
||||
{
|
||||
"upgrade_time": "2023-11-01 09:53:09",
|
||||
"upgrade_version": "v1.4.1",
|
||||
"pre_version": "v0.0.6.5",
|
||||
"upgrade_type": "1",
|
||||
"upgrade_desc": "",
|
||||
"device_sn": "G55HAP9LVQO2LAPM",
|
||||
"device_name": "G55HAP9LVQO2LAPM",
|
||||
"child_upgrade_records": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"trace_id": "9b3f6a74d73cbede9dcd7e3fa9f3c6de"
|
||||
}
|
|
@ -4,7 +4,7 @@
|
|||
"data": {
|
||||
"site_list": [
|
||||
{
|
||||
"site_id": "bdd7d770-bcb7-d22b-cafc-d0b2eddc4e23",
|
||||
"site_id": "9e40dc42-adac-7fba-dead-a1bba7bff34e",
|
||||
"site_name": "BKW",
|
||||
"site_img": "",
|
||||
"device_type_list": [
|
||||
|
@ -21,10 +21,10 @@
|
|||
"solarbank_list": [
|
||||
{
|
||||
"device_pn": "",
|
||||
"device_sn": "DILM86K2GJV2NRAI",
|
||||
"device_sn": "G55HAP9LVQO2LAPM",
|
||||
"device_name": "SB E1600",
|
||||
"device_img": "https://public-aiot-fra-prod.s3.dualstack.eu-central-1.amazonaws.com/anker-power/public/product/anker-power/e9478c2d-e665-4d84-95d7-dd4844f82055/20230719-144818.png",
|
||||
"battery_power": "6",
|
||||
"battery_power": "17",
|
||||
"bind_site_status": "1",
|
||||
"charging_power": "",
|
||||
"power_unit": "",
|
||||
|
@ -42,5 +42,5 @@
|
|||
],
|
||||
"powerpanel_list": []
|
||||
},
|
||||
"trace_id": "ae8abfd363866b4cee17359fd1cd9dca"
|
||||
"trace_id": "d0ee3c49869cec32cf6cf251521f29dd"
|
||||
}
|
|
@ -4,5 +4,5 @@
|
|||
"data": {
|
||||
"has_unread_msg": false
|
||||
},
|
||||
"trace_id": "aec8da3373cd0e59d9db5eb52e7adbdc"
|
||||
"trace_id": "a058ab399db309214abaabf12ddccaad"
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"code": 0,
|
||||
"msg": "success!",
|
||||
"data": {
|
||||
"is_ota_update": false,
|
||||
"need_retry": false,
|
||||
"retry_interval": 0,
|
||||
"device_list": null
|
||||
},
|
||||
"trace_id": "2dcfae1f2f344d0d97ac24d74ef8fba9"
|
||||
}
|
|
@ -19,5 +19,5 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"trace_id": "7a84aead0e446bbc85fc76ebbcb2bc01"
|
||||
"trace_id": "8bb7ef048b69dcff25ae45bc3ec3fad2"
|
||||
}
|
|
@ -2,10 +2,10 @@
|
|||
"code": 0,
|
||||
"msg": "success!",
|
||||
"data": {
|
||||
"site_id": "bdd7d770-bcb7-d22b-cafc-d0b2eddc4e23",
|
||||
"site_id": "9e40dc42-adac-7fba-dead-a1bba7bff34e",
|
||||
"price": 0.33,
|
||||
"site_co2": 0,
|
||||
"site_price_unit": "\u20ac"
|
||||
},
|
||||
"trace_id": "7cfacbfca09e909cf9a8939ebddba1ac"
|
||||
"trace_id": "5aae22e5adc38af4b9fdc37aa1f89cdb"
|
||||
}
|
|
@ -20,17 +20,17 @@
|
|||
"statistics": [
|
||||
{
|
||||
"type": "1",
|
||||
"total": "135.13",
|
||||
"total": "183.54",
|
||||
"unit": "kwh"
|
||||
},
|
||||
{
|
||||
"type": "2",
|
||||
"total": "134.72",
|
||||
"total": "182.99",
|
||||
"unit": "kg"
|
||||
},
|
||||
{
|
||||
"type": "3",
|
||||
"total": "44.59",
|
||||
"total": "60.57",
|
||||
"unit": "\u20ac"
|
||||
}
|
||||
],
|
||||
|
@ -39,40 +39,40 @@
|
|||
"solarbank_list": [
|
||||
{
|
||||
"device_pn": "A17C0",
|
||||
"device_sn": "DILM86K2GJV2NRAI",
|
||||
"device_sn": "G55HAP9LVQO2LAPM",
|
||||
"device_name": "SB E1600",
|
||||
"device_img": "https://public-aiot-fra-prod.s3.dualstack.eu-central-1.amazonaws.com/anker-power/public/product/anker-power/e9478c2d-e665-4d84-95d7-dd4844f82055/20230719-144818.png",
|
||||
"battery_power": "6",
|
||||
"battery_power": "17",
|
||||
"bind_site_status": "",
|
||||
"charging_power": "90",
|
||||
"charging_power": "190",
|
||||
"power_unit": "W",
|
||||
"charging_status": "3",
|
||||
"charging_status": "2",
|
||||
"status": "1",
|
||||
"wireless_type": "1",
|
||||
"main_version": "",
|
||||
"photovoltaic_power": "154",
|
||||
"output_power": "90",
|
||||
"photovoltaic_power": "0",
|
||||
"output_power": "190",
|
||||
"create_time": 1695392386,
|
||||
"set_load_power": "",
|
||||
"output_cutoff_data": 5,
|
||||
"is_display": true
|
||||
}
|
||||
],
|
||||
"total_charging_power": "64",
|
||||
"total_charging_power": "0",
|
||||
"power_unit": "W",
|
||||
"charging_status": "0",
|
||||
"total_battery_power": "0.06",
|
||||
"updated_time": "2024-03-27 11:49:04",
|
||||
"total_photovoltaic_power": "154",
|
||||
"total_output_power": "90.00",
|
||||
"total_battery_power": "0.17",
|
||||
"updated_time": "2024-04-24 01:33:08",
|
||||
"total_photovoltaic_power": "0",
|
||||
"total_output_power": "190.00",
|
||||
"display_set_power": false,
|
||||
"is_display_data": true
|
||||
},
|
||||
"retain_load": "0W",
|
||||
"retain_load": "300W",
|
||||
"updated_time": "01-01-0001 00:00:00",
|
||||
"power_site_type": 2,
|
||||
"site_id": "bdd7d770-bcb7-d22b-cafc-d0b2eddc4e23",
|
||||
"site_id": "9e40dc42-adac-7fba-dead-a1bba7bff34e",
|
||||
"powerpanel_list": []
|
||||
},
|
||||
"trace_id": "e6a2f3f712a7c2498a25ae7c0bafef3e"
|
||||
"trace_id": "64eeaeab8d80ee6bab68bf981b9cda1d"
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
"msg": "success!",
|
||||
"data": {
|
||||
"site_info": {
|
||||
"site_id": "bdd7d770-bcb7-d22b-cafc-d0b2eddc4e23",
|
||||
"site_id": "9e40dc42-adac-7fba-dead-a1bba7bff34e",
|
||||
"site_name": "BKW",
|
||||
"site_img": "",
|
||||
"device_type_list": [
|
||||
|
@ -23,7 +23,7 @@
|
|||
"solarbank_list": [
|
||||
{
|
||||
"device_pn": "A17C0",
|
||||
"device_sn": "DILM86K2GJV2NRAI",
|
||||
"device_sn": "G55HAP9LVQO2LAPM",
|
||||
"device_name": "SB E1600",
|
||||
"device_img": "https://public-aiot-fra-prod.s3.dualstack.eu-central-1.amazonaws.com/anker-power/public/product/anker-power/e9478c2d-e665-4d84-95d7-dd4844f82055/20230719-144818.png",
|
||||
"battery_power": "",
|
||||
|
@ -44,5 +44,5 @@
|
|||
],
|
||||
"powerpanel_list": []
|
||||
},
|
||||
"trace_id": "84caedc36bfe9b3f0ed1c89ceb5c0ee2"
|
||||
"trace_id": "daee0eafcbcefbcafc9a0adb3519ea6f"
|
||||
}
|
|
@ -4,7 +4,7 @@
|
|||
"data": {
|
||||
"site_list": [
|
||||
{
|
||||
"site_id": "bdd7d770-bcb7-d22b-cafc-d0b2eddc4e23",
|
||||
"site_id": "9e40dc42-adac-7fba-dead-a1bba7bff34e",
|
||||
"site_name": "BKW",
|
||||
"site_img": "",
|
||||
"device_type_list": [
|
||||
|
@ -21,5 +21,5 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"trace_id": "b07e6dfde00e7ddfb8fa4b3a2b76ac4c"
|
||||
"trace_id": "fe909473eeb4bd6ba428b4fda59aab74"
|
||||
}
|
|
@ -142,5 +142,5 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"trace_id": "d3dceb28da9a8f8ca2fb2ae170dc186a"
|
||||
"trace_id": "f8acb37f7d12aeabe646cbd5055ebabf"
|
||||
}
|
|
@ -5,8 +5,8 @@
|
|||
"brand_id": "3a9930f5-74ef-4e41-a797-04e6b33d3f0f",
|
||||
"solar_brand": "ANKER",
|
||||
"solar_model": "A5143",
|
||||
"solar_sn": "9XK0FGWY2TWW",
|
||||
"solar_sn": "YTZL4ZEJ4R5B",
|
||||
"solar_model_name": "MI80 Microinverter(BLE)"
|
||||
},
|
||||
"trace_id": "4fddaabaeaabd39fea6d7c474fb97ad2"
|
||||
"trace_id": "6b2dfaebd1abe931bcec042c1686fc4f"
|
||||
}
|
|
@ -7,7 +7,7 @@
|
|||
"solarbank_list": [
|
||||
{
|
||||
"device_pn": "A17C0",
|
||||
"device_sn": "DILM86K2GJV2NRAI",
|
||||
"device_sn": "G55HAP9LVQO2LAPM",
|
||||
"device_name": "SB E1600",
|
||||
"device_img": "https://public-aiot-fra-prod.s3.dualstack.eu-central-1.amazonaws.com/anker-power/public/product/anker-power/e9478c2d-e665-4d84-95d7-dd4844f82055/20230719-144818.png",
|
||||
"battery_power": "",
|
||||
|
@ -28,5 +28,5 @@
|
|||
],
|
||||
"powerpanel_list": []
|
||||
},
|
||||
"trace_id": "3607fa3ff416d93ded855c2ee9b10bea"
|
||||
"trace_id": "4acd422dafadcb3f2ccabbe1fb92ceda"
|
||||
}
|
|
@ -5,9 +5,9 @@
|
|||
"wifi_info_list": [
|
||||
{
|
||||
"wifi_name": "wifi-network-1",
|
||||
"wifi_signal": "54"
|
||||
"wifi_signal": "50"
|
||||
}
|
||||
]
|
||||
},
|
||||
"trace_id": "38ec9a1a8d29dac96ac9adc12fbb41b8"
|
||||
"trace_id": "af7beabd3e81cfb62be0f4abf96298fb"
|
||||
}
|
|
@ -50,7 +50,8 @@ def randomize(val, key: str = "") -> str:
|
|||
if not RANDOMIZE:
|
||||
return str(val)
|
||||
randomstr = RANDOMDATA.get(val, "")
|
||||
if not randomstr and val:
|
||||
# generate new random string
|
||||
if not randomstr and val and key not in ["device_name"]:
|
||||
if "_sn" in key or key in ["sn"]:
|
||||
randomstr = "".join(
|
||||
random.choices(string.ascii_uppercase + string.digits, k=len(val))
|
||||
|
@ -68,7 +69,7 @@ def randomize(val, key: str = "") -> str:
|
|||
if ":" in val:
|
||||
RANDOMDATA.update({temp: randomstr}) # save also key value without :
|
||||
randomstr = ":".join(
|
||||
a + b for a, b in zip(randomstr[::2], randomstr[1::2])
|
||||
a + b for a, b in zip(randomstr[::2], randomstr[1::2], strict=False)
|
||||
)
|
||||
elif "_id" in key:
|
||||
for part in val.split("-"):
|
||||
|
@ -102,7 +103,7 @@ def randomize(val, key: str = "") -> str:
|
|||
# default randomize format
|
||||
randomstr = "".join(random.choices(string.ascii_letters, k=len(val)))
|
||||
RANDOMDATA.update({val: randomstr})
|
||||
return randomstr
|
||||
return randomstr or str(val)
|
||||
|
||||
|
||||
def check_keys(data):
|
||||
|
@ -125,6 +126,7 @@ def check_keys(data):
|
|||
"wifi_name",
|
||||
"home_load_data",
|
||||
"param_data",
|
||||
"device_name"
|
||||
]
|
||||
) or k in ["sn"]:
|
||||
data[k] = randomize(v, k)
|
||||
|
@ -133,7 +135,7 @@ def check_keys(data):
|
|||
|
||||
def export(
|
||||
filename: str,
|
||||
d: dict = None,
|
||||
d: dict | None = None,
|
||||
skip_randomize: bool = False,
|
||||
randomkeys: bool = False,
|
||||
) -> None:
|
||||
|
@ -329,6 +331,22 @@ async def main() -> bool: # noqa: C901 # pylint: disable=too-many-branches,too-
|
|||
except (ClientError, errors.AnkerSolixError):
|
||||
if not admin:
|
||||
CONSOLE.warning("Query requires account of site owner!")
|
||||
CONSOLE.info("Exporting site upgrade record...")
|
||||
try:
|
||||
export(
|
||||
os.path.join(
|
||||
folder,
|
||||
f"get_upgrade_record_{randomize(siteId,'site_id')}.json",
|
||||
),
|
||||
await myapi.request(
|
||||
"post",
|
||||
api._API_ENDPOINTS["get_upgrade_record"],
|
||||
json={"site_id": siteId, "type": 2},
|
||||
),
|
||||
) # works only for site owners
|
||||
except (ClientError, errors.AnkerSolixError):
|
||||
if not admin:
|
||||
CONSOLE.warning("Query requires account of site owner!")
|
||||
for sn, device in myapi.devices.items():
|
||||
CONSOLE.info(
|
||||
"\nExporting device specific data for device %s SN %s...",
|
||||
|
@ -414,6 +432,19 @@ async def main() -> bool: # noqa: C901 # pylint: disable=too-many-branches,too-
|
|||
except (ClientError, errors.AnkerSolixError):
|
||||
if not admin:
|
||||
CONSOLE.warning("Query requires account of site owner!")
|
||||
CONSOLE.info("Exporting OTA update info...")
|
||||
try:
|
||||
export(
|
||||
os.path.join(folder, f"ota_update_{randomize(sn,'_sn')}.json"),
|
||||
await myapi.request(
|
||||
"post",
|
||||
api._API_ENDPOINTS["get_ota_update"],
|
||||
json={"device_sn": sn, "insert_sn": ""},
|
||||
),
|
||||
) # works only for site owners
|
||||
except (ClientError, errors.AnkerSolixError):
|
||||
if not admin:
|
||||
CONSOLE.warning("Query requires account of site owner!")
|
||||
|
||||
CONSOLE.info("\nExporting site rules...")
|
||||
export(
|
||||
|
|
Loading…
Reference in New Issue