/api/device/settings/v1
and /api/device/settings/update/v1 do not exist on solar.siseli.com. Replaced with the
correct remote-config API endpoints discovered from the live portal JS bundle:
POST /apis/remote/device/configs/cache/get?deviceId=<id> (plain IOT-Token header)POST /apis/remote/device/config/write?deviceId=<id> (body {deviceId, key, value})select.py — Operating Mode select now uses real API key outputSourcePrioritySetting
with options Utility First (USO) / Solar First (SUB) / Solar+Battery First (SBU).select.py — Battery Priority select now uses real API key chargerSourcePrioritySetting
with options Solar + Utility (CSO) / Solar First (SNU) / Solar Only (OSO).switch.py — Grid Feed-In switch maps to batteryPowerLimitingSetting (0=OFF, 1=ON).switch.py — Grid Charging switch maps to acInputRangeSetting (0=Appliance/ON, 1=UPS/OFF).switch.py — Backup Mode switch maps to outputSourcePrioritySetting SBU=2 (ON) / SUB=1 (OFF).api.py — get_device_settings / fetch_settings now POST to the correct URL with query
parameter and plain IOT-Token header (no IOT-Open signing required for this endpoint).api.py — _write_setting helper added; set_* control methods updated with correct
API key names and integer value mappings (no longer sending arbitrary string names).All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
fetch_settings AttributeError -- __init__.py called api.fetch_settings()
but api.py only exposed get_device_settings(). Added fetch_settings as a
class-level alias so both names work.select.py and switch.py called five
methods that did not exist on SolarOfThingsAPI:
set_operating_mode, set_battery_priority, set_grid_charging,
set_grid_feed_in, set_backup_mode. All five are now implemented as thin
wrappers over update_device_settings.rBrTRfAPXz (production) targeting https://solar.siseli.com.
The previous release used the test-environment AppID (JO4DAiNeys) which was
only accepted by test.solar.siseli.com, causing "account error" (code 20007)
for every real user account.MD5(plaintext_password) (lowercase hex) in the login payload. Sending plain
text returned code 7 "password error" even with valid credentials. The login
method now applies hashlib.md5(password).hexdigest() before building the
JSON body, matching the portal behaviour confirmed by live API testing.API_AUTH_BASE_URL changed from https://test.solar.siseli.com to https://solar.siseli.com.IOT_APP_ID changed from JO4DAiNeys to rBrTRfAPXz.IOT_APP_SECRET_ENC updated to the production-AppID encrypted secret.CONF_EMAIL config key is replaced by CONF_USER_ID (user_id).
The login payload now sends {"account": ..., "password": ...} matching
the Siseli portal's account-login flow.umi.js bundle:
AES-128-CBC(base64(enc_secret), key=MD5(appID)[:16], iv=MD5(appID)[16:]).MD5(HMAC-SHA256(base64(sorted_qs_headers), decrypted_secret)).test.solar.siseli.com/apis/login/account
and confirmed to return code 20007 (invalid credentials) rather than the
previous code 44 (sign error) — proving the signing is now accepted by the server.https://test.solar.siseli.com (as hardcoded in portal JS).https://solar.siseli.com (unchanged)./login/account (404) → /apis/login/account (200).API_AUTH_BASE_URL, IOT_APP_ID, IOT_APP_SECRET_ENC constants in const.py._decrypt_app_secret(), _compute_iot_sign(), _make_signed_headers() helpers in api.py.pycryptodome>=3.9.0 added to manifest.json requirements for AES decryption.Existing entries that used email for auth will need to re-authenticate:
Home Assistant will show a re-auth prompt where you enter your User ID and password.
email, password) and handles the full token lifecycle automatically. Users no longer need to copy IOT tokens from DevTools.SolarOfThingsAPI._ensure_token_valid() proactively refreshes the access token 5 minutes before expiry using POST /login/refresh/access/token (mirroring the portal JS behaviour). Falls back to re-login with stored credentials if the refresh token has also expired.entry.async_start_reauth() so HA displays a notification and the user is guided through re-authentication without losing their config.on_token_refreshed callback — fresh tokens are persisted back to the config entry after every refresh, so the integration survives HA restarts without a new login.const.py keys: CONF_EMAIL, CONF_PASSWORD, CONF_REFRESH_TOKEN, CONF_ACCESS_TOKEN_EXPIRES, CONF_REFRESH_TOKEN_EXPIRES, API_LOGIN, API_REFRESH_TOKEN, TOKEN_REFRESH_LEAD_SECONDS.password, token, reauth_confirm (step user now offers a mode selector).TokenExpiredError and AuthenticationError custom exceptions in api.py.SolarOfThingsAPI.__init__ signature updated: keyword-only arguments (email, password, iot_token, refresh_token, etc.).__init__.py coordinators now catch TokenExpiredError and trigger re-auth instead of silently failing.strings.json / translations/en.json updated for new flow steps and error messages.manifest.json version bumped to 2.2.0 (config_flow version bumped to 3).loginType field value and exact shape of the /login/account response are inferred from portal JS analysis; tested against live API but may need adjustment for non-email login types.POST /login/refresh/access/token; falls back to re-login with stored credentials.entry.async_start_reauth() to prompt user without losing config.on_token_refreshed callback — fresh tokens persisted to config entry after every refresh (survives HA restarts).CONF_EMAIL, CONF_PASSWORD, CONF_REFRESH_TOKEN, CONF_ACCESS_TOKEN_EXPIRES, CONF_REFRESH_TOKEN_EXPIRES, API_LOGIN, API_REFRESH_TOKEN, TOKEN_REFRESH_LEAD_SECONDS.password, token, reauth_confirm; step user is now a mode selector.TokenExpiredError and AuthenticationError custom exceptions in api.py.SolarOfThingsAPI.__init__ uses keyword-only arguments.TokenExpiredError and trigger re-auth.strings.json/translations/en.json updated for new flow steps.manifest.json version 2.2.0, config flow VERSION = 3..github/PULL_REQUEST_TEMPLATE.md — standardised PR template for HACS default submission.hacs.json updated: added all integration platforms (sensor, number, select, switch), enabled zip_release: true, and set filename: solar-of-things-ha.zip so HACS fetches the correct release asset.manifest.json version bumped to 2.1.1.POST /apis/device/list (no need to manually enter deviceId).device_id:
device_id to restrict HA entities to a single device./api/device/settings/v1, /api/device/settings/update/v1To upgrade to a new version:
Via HACS:
Manual:
/config/custom_components/solar_of_things/None yet (version 1.0.0)
None required for version 1.0.0
Each release includes:
For questions about changes or upgrade issues: