Summary
Newer LG ESS Home firmware (PMS 10.05.x and above) has shortened the auth endpoints. The library still calls the old paths, so every login attempt to a current device fails with password mismatched (the ESS returns 404 for the old URL, which the client mis-interprets as a wrong password), and the time-sync step then loops. This issue describes the problem and proposes a fix.
Environment
- Device: LG ESS Home 10 Hybrid inverter
- Model: D010KE1N211
- Serial: DE2112BKRE0078C5
- Firmware:
- PMS 10.05.7438
- PCS LG 05.00.01.00
- BMS 02.03.00.04
- Library version tested: pyess 0.1.15 (also reproducible on 0.1.23)
- Used by: dkarv/ha-lg-ess (Home Assistant integration)
Endpoint mismatch
| Step |
pyess (old, hard-coded) |
Newer LG firmware actually exposes |
| Login (auth_key) |
PUT /v1/user/setting/login |
PUT /v1/login |
| Time sync |
PUT /v1/user/setting/timesync |
PUT /v1/timesync (returns 404 on this firmware — see note) |
The old login path now returns 404 from the device. The client never sees a real password mismatched body, so the failure surfaces as wrong password in ESSAuthException, which is misleading — the password is fine.
The timesync path is a separate story: PUT /v1/timesync is not implemented on this PMS 10.05 build (returns 404). Time sync is harmless to skip on current firmware, but the library currently treats that 404 as a JSON-decode error and retries the whole login in a tight loop, which is what breaks long-running integrations (HA logs fill with sign invalid / repeated retries).
Reproduction
# 1. Direct check — what the firmware actually answers:
curl -i -k -X PUT 'https://<ess-ip>/v1/login' \
-H 'Content-Type: application/json' \
-d '{"password":"YOUR_PASSWORD"}'
# HTTP/1.1 200 OK + {"auth_key":"...","status":"success"}
curl -i -k -X PUT 'https://<ess-ip>/v1/user/setting/login' \
-H 'Content-Type: application/json' \
-d '{"password":"YOUR_PASSWORD"}'
# HTTP/1.1 404 Not Found
# 2. From pyess, the same call produces:
# pyess.aio_ess.ESSAuthException: wrong password
# (root cause: the URL is wrong, not the password)
Where the URLs live in the code
pyess/constants.py:
PREFIX = "https://{}/"
LOGIN_URL = f"{PREFIX}v1/user/setting/login"
TIMESYNC_URL = f"{PREFIX}v1/user/setting/timesync"
pyess/aio_ess.py (line 50/63):
url = LOGIN_URL.format(self.ip) # _login()
...
async with self.session.put(TIMESYNC_URL.format(self.ip), json=timesync_info) as r:
Proposed fix
Two changes, both small:
-
Update the URL constants in pyess/constants.py to the new shorter paths:
PREFIX = "https://{}/"
LOGIN_URL = f"{PREFIX}v1/login"
TIMESYNC_URL = f"{PREFIX}v1/timesync"
-
Make time-sync tolerant in pyess/aio_ess.py _login(): if the timesync PUT returns 404 (or any non-2xx with a non-JSON body), treat it as "not supported on this firmware" and continue with self.auth_key = auth_key; self.logged_in = True. The login itself works fine without timesync on PMS 10.05+ — the device's own clock is good enough for the polling intervals the library uses.
Optionally, also normalise the error message: if LOGIN_URL returns 404, retry once with the legacy path (/v1/user/setting/login) before raising ESSAuthException("wrong password"). That way both old and new firmware keep working without forcing the user to pick a version.
Workaround in the meantime
Until a release is cut, I (and other HA users) are patching the installed copy with a sed hook in our HA image build, because the HA container image update otherwise silently overwrites the fix:
sed -i 's|v1/user/setting/login|v1/login|g' \
/usr/src/homeassistant/homeassistant/components/lg_ess/pyess/constants.py
sed -i 's|v1/user/setting/timesync|v1/timesync|g' \
/usr/src/homeassistant/homeassistant/components/lg_ess/pyess/constants.py
That's not a long-term solution — it gets clobbered on every image update — so an upstream fix in pyess would unblock everyone on current LG firmware.
Happy to send a PR with the changes above if useful; just let me know which fix shape you prefer (auto-fallback vs. just-point-at-new-URL).
Summary
Newer LG ESS Home firmware (PMS 10.05.x and above) has shortened the auth endpoints. The library still calls the old paths, so every login attempt to a current device fails with
password mismatched(the ESS returns 404 for the old URL, which the client mis-interprets as a wrong password), and the time-sync step then loops. This issue describes the problem and proposes a fix.Environment
Endpoint mismatch
PUT /v1/user/setting/loginPUT /v1/loginPUT /v1/user/setting/timesyncPUT /v1/timesync(returns 404 on this firmware — see note)The old login path now returns 404 from the device. The client never sees a real
password mismatchedbody, so the failure surfaces aswrong passwordinESSAuthException, which is misleading — the password is fine.The
timesyncpath is a separate story:PUT /v1/timesyncis not implemented on this PMS 10.05 build (returns 404). Time sync is harmless to skip on current firmware, but the library currently treats that 404 as a JSON-decode error and retries the whole login in a tight loop, which is what breaks long-running integrations (HA logs fill withsign invalid/ repeated retries).Reproduction
Where the URLs live in the code
pyess/constants.py:pyess/aio_ess.py(line 50/63):Proposed fix
Two changes, both small:
Update the URL constants in
pyess/constants.pyto the new shorter paths:Make time-sync tolerant in
pyess/aio_ess.py_login(): if the timesync PUT returns 404 (or any non-2xx with a non-JSON body), treat it as "not supported on this firmware" and continue withself.auth_key = auth_key; self.logged_in = True. The login itself works fine without timesync on PMS 10.05+ — the device's own clock is good enough for the polling intervals the library uses.Optionally, also normalise the error message: if
LOGIN_URLreturns 404, retry once with the legacy path (/v1/user/setting/login) before raisingESSAuthException("wrong password"). That way both old and new firmware keep working without forcing the user to pick a version.Workaround in the meantime
Until a release is cut, I (and other HA users) are patching the installed copy with a
sedhook in our HA image build, because the HA container image update otherwise silently overwrites the fix:That's not a long-term solution — it gets clobbered on every image update — so an upstream fix in pyess would unblock everyone on current LG firmware.
Happy to send a PR with the changes above if useful; just let me know which fix shape you prefer (auto-fallback vs. just-point-at-new-URL).