Skip to content

Add opt-in AlphaESSApiError so callers can detect API failures - #29

Merged
CharlesGillanders merged 3 commits into
CharlesGillanders:mainfrom
Poshy163:feat/api-error-detection
Aug 13, 2026
Merged

Add opt-in AlphaESSApiError so callers can detect API failures#29
CharlesGillanders merged 3 commits into
CharlesGillanders:mainfrom
Poshy163:feat/api-error-detection

Conversation

@Poshy163

@Poshy163 Poshy163 commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

The write endpoints answer with data: null whether they succeed or fail, and api_post returns
json_response["data"] on success and None on failure. So a successful write looks identical to
a rejected one and callers are left guessing.

This adds raise_on_error, off by default. Leave it alone and nothing changes: API-level failures
log and return None as always. Turn it on and they raise AlphaESSApiError with code, msg,
expMsg, description and path attached, so success becomes "nothing was raised" instead of a
return value nobody can interpret.

client = alphaess(appID, appSecret, raise_on_error=True)
try:
    await client.setTimeChargeBySn(sysSn, 0, charge_list, discharge_list)
except AlphaESSApiError as err:
    print(err.code, err.expMsg)   # 6001 "time list is null"

Backwards compatibility

  • no return type or value changes anywhere
  • raise_on_error goes last in __init__, so positional callers are unaffected
  • transport errors propagate exactly as before
  • the existing 34 tests pass untouched, and homeassistant-alphaESS's 342 pass against this build
    without opting in

getdata() stays best-effort with the flag on — a refused endpoint leaves that key None rather
than costing the whole poll, since getTimeChargeBySn answers 6017 on most systems.

Bumped to 0.0.21.

Doc corrections, checked against the live API

  • An empty period list is rejected with 6001 "time list is null"Document the full API, add periodic charge/discharge endpoints, fix error handling #28 said [] was fine,
    which was wrong. Omitting a list gives 10001, outside the 6xxx range and not in the portal's
    table.
  • Parameters are validated before permissions, so an early 6001 doesn't mean your account has
    access — you just never got far enough to find out.
  • expMsg is often the only field naming the bad parameter, and was neither logged nor exposed.
  • There are 21 endpoints in the portal, not 19. getMeterOffsetConfigInfo and
    updateMeterOffsetConfigInfo are scoped to the commercial & industrial document, so a standard
    account can't reach them. Documented, not implemented. The portal lists the getter as POST; it's
    GET, and POST returns 405.

The write endpoints answer with data: null whether they succeed or fail, and
api_post returns json_response["data"] on success and None on failure, so a
successful write is indistinguishable from a rejected one. That left callers
guessing, which is how homeassistant-alphaESS ended up gating a write on an
unrelated read.

Add raise_on_error, defaulting to False. Left alone nothing changes: API-level
failures still log and return None. Set it and they raise AlphaESSApiError
carrying code, msg, expMsg, description and path, so success becomes "did not
raise" rather than a return value nobody can interpret.

Kept backwards compatible on purpose, since people upgrade without reading
changelogs:
  - no return type or value changes anywhere
  - raise_on_error is appended last in __init__, so positional callers are fine
  - transport exceptions propagate exactly as before
  - the existing 34 tests pass untouched, and homeassistant-alphaESS's 342
    tests pass against this build without opting in

Also verified against the live API and corrected in the docs:
  - an empty period list is rejected with 6001 "time list is null"; the docs
    previously claimed [] was acceptable. Omitting one gives 10001, a code
    outside the 6xxx range and absent from the portal's table.
  - parameter validation runs before the entitlement check, so an early 6001
    is not evidence that the account has permission
  - expMsg is often the only field naming the bad parameter, and was neither
    logged nor exposed
  - the portal registry holds 21 interfaces, not 19: getMeterOffsetConfigInfo
    and updateMeterOffsetConfigInfo are scoped to the commercial & industrial
    document and are not callable from a standard account
  - getMeterOffsetConfigInfo is GET; the portal documents it as POST, which 405s
The "already logged by __handle_failure" note was on all 25 passthroughs and
said the same thing every time, which is noise once you've read it once.

Also reworded the new doc sections so they read like someone explaining what
they found rather than a spec, and cut the paragraph restating what the table
above it already said.
getdata is documented as returning whatever it managed to gather, but with the
flag set the first endpoint the account can't use would raise and take the
whole poll with it. getTimeChargeBySn answers 6017 on most systems, so that was
not a corner case.

Each call inside getdata now goes through _best_effort, which leaves that one
key None on a refusal. Transport errors still stop it, since those affect every
endpoint anyway.
@Poshy163
Poshy163 marked this pull request as ready for review August 13, 2026 06:55
@Poshy163

Copy link
Copy Markdown
Contributor Author

@CharlesGillanders bump, also needs a release so CharlesGillanders/homeassistant-alphaESS#270 can be finished off

@CharlesGillanders
CharlesGillanders merged commit 768a71f into CharlesGillanders:main Aug 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants