Skip to content

feat: keep SAIC’s return code and message on every error (#54) - #55

Merged
nanomad merged 2 commits into
SAIC-iSmart-API:developfrom
townsmcp:feat/error-codes
Oct 25, 2026
Merged

nanomad merged 2 commits into
SAIC-iSmart-API:developfrom
townsmcp:feat/error-codes

Conversation

@townsmcp

Copy link
Copy Markdown

Closes #54. Part of #26.

SaicApiException now keeps SAIC's reply as separate values, so callers don't have to parse str(e) to find out why a call failed.

Changes

  • return_code and saic_message: new attributes on SaicApiException and all its subclasses. return_code is SAIC's numeric code (or None); saic_message is the message on its own.
  • SaicReturnCode: a new enum of the codes with a known meaning:
Code Name Meaning
0 SUCCESS
4 VEHICLE_UNREACHABLE the car can't be reached, e.g. asleep
6 SERVICE_UNAVAILABLE
8 REQUEST_REJECTED refused, for several reasons: read the message
401 / 403 UNAUTHORIZED / FORBIDDEN session no longer valid
500 UNEXPECTED_FAILURE the library's own code for an unexpected failure

Codes not listed still come through unchanged in return_code.

  • Checks for the common cases: is_vehicle_unreachable, is_request_rejected, is_vehicle_not_locked (code 8 with "not locked" in the message, as opposed to the remote command limit, which is also code 8), is_logged_out (always true on SaicLogoutException) and is_unexpected_failure.
  • Exceptions now call super().__init__(), so e.args is set and they pickle cleanly.
  • str(e) is unchanged ("return code: <code>, message: <message>", or just the message), including SaicApiRetryException's event_id suffix. Existing code that reads the text keeps working.

Tests

tests/test_exceptions.py covers:

  • the unchanged text, args and pickling;
  • each check across codes 4, 6, 8 (both "not locked" and the command limit), 401, 403 and no code;
  • the retry and logout exceptions;
  • two cases through the real response handling: a code-8 "Vehicle not locked." reply, and a code-4 reply during event polling.

Notes

  • README: a short "Errors" section, added at the end.
  • No dependencies: this PR is independent of the seat and window PRs and merges cleanly alongside them.
  • Checks: ruff (check and format), mypy, pylint and pytest all pass locally on Python 3.13.

townsmcp and others added 2 commits October 25, 2026 12:14
…-API#54)

SaicApiException now keeps the return code and SAIC's message as separate
attributes (return_code, saic_message) and offers checks for the common
cases (is_vehicle_unreachable, is_request_rejected, is_vehicle_not_locked,
is_logged_out, is_unexpected_failure), with the known codes in
SaicReturnCode. str(e) is unchanged, so code that reads the text keeps
working.
@nanomad
nanomad changed the base branch from master to develop October 25, 2026 14:14
@nanomad
nanomad merged commit 30682ca into SAIC-iSmart-API:develop Oct 25, 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.

Expose SAIC’s return code and message on exceptions

2 participants