Skip to content

feat(svm): add SVM / Find My Car support for Hyundai BlueLink USA - #1203

Open
blka wants to merge 19 commits into
Hyundai-Kia-Connect:masterfrom
blka:feature/svm-usa-support
Open

feat(svm): add SVM / Find My Car support for Hyundai BlueLink USA#1203
blka wants to merge 19 commits into
Hyundai-Kia-Connect:masterfrom
blka:feature/svm-usa-support

Conversation

@blka

@blka blka commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds 360 Surround View Monitor (SVM) / Find My Car support for Hyundai BlueLink USA, including automatic capability detection.

Closes #1201
Related to discussion #1194

New API surface

from hyundai_kia_connect_api import SVMDetails
from hyundai_kia_connect_api.HyundaiBlueLinkApiUSA import HyundaiBlueLinkApiUSA

# Retrieve latest cached composite image + metadata
details = api.get_svm_details(token, vehicle)

# Trigger a fresh capture (acknowledgment required)
details = api.request_svm_capture(token, vehicle, acknowledged_warning=True)

# Check whether a vehicle supports SVM (lazy probe, cached result)
is_supported = manager.supports_svm(vehicle.id)

What changed

  • hyundai_kia_connect_api/svm.py: SVMDetails dataclass, response parser, and log-redaction helpers.
  • hyundai_kia_connect_api/exceptions.py: SafetyAcknowledgmentError.
  • hyundai_kia_connect_api/ApiImpl.py: base stubs raising NotImplementedError for other regions, plus base supports_svm returning a cached value or False.
  • hyundai_kia_connect_api/HyundaiBlueLinkApiUSA.py: concrete implementation of get_svm_details, request_svm_capture, and supports_svm.
    • request_svm_capture performs a baseline GET, POSTs the trigger, maps HT_533 to DuplicateRequestError, and polls for up to 120 s until the capture timestamp changes.
    • supports_svm probes get_svm_details once, caches the result on Vehicle, and maps all failures to False.
  • hyundai_kia_connect_api/Vehicle.py: new supports_svm field for cached capability detection.
  • hyundai_kia_connect_api/VehicleManager.py: new supports_svm(vehicle_id) consumer-facing wrapper.
  • hyundai_kia_connect_api/__init__.py: exports SVMDetails.
  • tests/us_svm_test.py: unit tests for SVM response parsing, redaction, polling, errors, and capability detection.
  • .ruff.toml: sets target-version = "py310" to prevent Python 3.10 syntax regressions (bare multi-exception except was accepted by the default target).

Privacy

  • Debug logs redact svmImage and GPS coordinates.
  • SVMDetails.raw_metadata stores the full response dict with svmImage replaced by <redacted>.
  • request_svm_capture logs only the tid from the trigger response.

Verification

ruff check .
ruff format .
pytest -q
# all tests pass

Live verification

Verified against a real Hyundai USA 2025 Tucson Hybrid account by @ijojog:

  • get_svm_details returned a valid 177 kB JPG composite with full metadata.
  • request_svm_capture(..., acknowledged_warning=True) triggered, polled, and returned a newer 167 kB image.
  • supports_svm correctly detected the feature as available for this vehicle.
  • Image dimensions were consistently 4472 × 720.
  • Metadata (heading, door/trunk, speed) parsed correctly.
  • No DuplicateRequestError or authentication issues occurred.

Scope

  • USA Hyundai only.
  • V1 returns the full composite JPG; panel cropping is out of scope.
  • HA integration follow-up will be handled in a separate PR.

@blka
blka marked this pull request as draft June 24, 2026 07:44
@blka

blka commented Jun 24, 2026

Copy link
Copy Markdown
Contributor Author

@ijojog — here's a standalone test script you can run against this PR to verify the SVM implementation with your live account.

Quick start

  1. Check out this PR branch (feature/svm-usa-support).
  2. Install the library + python-dotenv:
python -m pip install -e .
python -m pip install python-dotenv
  1. Create a .env file next to the script with your credentials:
HYUNDAI_USERNAME=you@example.com
HYUNDAI_PASSWORD=yourpassword
HYUNDAI_PIN=1234
  1. Save the script below as test_svm_usa.py and run it:
python test_svm_usa.py

Use --skip-capture to only test get_svm_details without triggering a new capture:

python test_svm_usa.py --skip-capture

What it does

  • Logs in via VehicleManager.
  • Calls api.get_svm_details(...) and writes svm_latest.jpg.
  • Calls api.request_svm_capture(..., acknowledged_warning=True) and writes svm_fresh.jpg.
  • Prints image size, capture timestamp, heading, door/trunk state, and image dimensions.
  • Does not print credentials, tokens, GPS coordinates, or base64 image data.

Expected results

  • svm_latest.jpg should be a valid JPG composite (~200–300 KB).
  • svm_fresh.jpg should have a newer timestamp than svm_latest.jpg.
  • If you hit a pending/cooldown error, the script prints a clear message and exits cleanly.

Test script

"""Standalone test script for Hyundai BlueLink USA SVM support.

Usage:
    1. Install the library in editable mode:
       python -m pip install -e .

    2. Create a .env file next to this script:
       HYUNDAI_USERNAME=you@example.com
       HYUNDAI_PASSWORD=yourpassword
       HYUNDAI_PIN=1234

    3. Run:
       python test_svm_usa.py

The script writes two files to the current directory:
    - svm_latest.jpg      latest cached composite from get_svm_details
    - svm_fresh.jpg       freshly captured composite from request_svm_capture

Credentials, tokens, GPS coordinates, and image base64 are never printed.
"""
from __future__ import annotations

import argparse
import logging
import os
import sys
from pathlib import Path

from dotenv import load_dotenv

from hyundai_kia_connect_api.VehicleManager import VehicleManager
from hyundai_kia_connect_api.const import BRAND_HYUNDAI, REGION_USA
from hyundai_kia_connect_api.exceptions import (
    APIError,
    DuplicateRequestError,
    SafetyAcknowledgmentError,
)

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s %(levelname)s %(name)s - %(message)s",
)


def _load_env():
    env_path = Path(__file__).with_suffix(".env")
    if env_path.exists():
        load_dotenv(env_path)
    load_dotenv()


def _get_manager():
    username = os.environ.get("HYUNDAI_USERNAME")
    password = os.environ.get("HYUNDAI_PASSWORD")
    pin = os.environ.get("HYUNDAI_PIN")

    missing = [
        k
        for k, v in {
            "HYUNDAI_USERNAME": username,
            "HYUNDAI_PASSWORD": password,
            "HYUNDAI_PIN": pin,
        }.items()
        if not v
    ]
    if missing:
        raise SystemExit(
            f"Missing environment variables: {', '.join(missing)}. "
            "Set them in a .env file or export them."
        )

    manager = VehicleManager(
        region=REGION_USA,
        brand=BRAND_HYUNDAI,
        username=username,
        password=password,
        pin=pin,
        geocode_api_enable=False,
    )
    return manager


def _describe_details(details, label: str):
    print(f"\n{label}")
    print(f"  image size: {len(details.image_bytes)} bytes")
    print(f"  captured at: {details.captured_at}")
    print(f"  heading: {details.heading}")
    print(f"  speed: {details.speed}")
    print(f"  door open: {details.door_open}")
    print(f"  trunk open: {details.trunk_open}")
    print(f"  image dimensions: {details.image_size}")


def main():
    parser = argparse.ArgumentParser(description="Test SVM support for Hyundai USA")
    parser.add_argument(
        "--skip-capture",
        action="store_true",
        help="Only test get_svm_details, do not trigger a new capture",
    )
    args = parser.parse_args()

    _load_env()
    manager = _get_manager()

    print("Logging in...")
    login_result = manager.login()
    if login_result is not True:
        raise SystemExit(f"Login did not succeed: {login_result}")

    if not manager.vehicles:
        raise SystemExit("No vehicles found on this account.")

    vehicle = next(iter(manager.vehicles.values()))
    print(f"Using vehicle: {vehicle.name} ({vehicle.VIN})")

    api = manager.api
    token = manager.token

    print("Fetching latest cached SVM image...")
    try:
        latest = api.get_svm_details(token, vehicle)
    except APIError as exc:
        raise SystemExit(f"get_svm_details failed: {exc}") from exc

    _describe_details(latest, "get_svm_details result")
    Path("svm_latest.jpg").write_bytes(latest.image_bytes)
    print("  saved: svm_latest.jpg")

    if args.skip_capture:
        print("\n--skip-capture: skipping request_svm_capture")
        return 0

    print("\nTriggering fresh SVM capture...")
    print("(this may take up to ~120 seconds as the library polls for the new image)")
    try:
        fresh = api.request_svm_capture(
            token, vehicle, acknowledged_warning=True
        )
    except SafetyAcknowledgmentError as exc:
        raise SystemExit(f"Safety acknowledgment required: {exc}") from exc
    except DuplicateRequestError as exc:
        print(f"\nPrevious SVM request is still pending: {exc}")
        print("Wait a few minutes and try again, or use --skip-capture.")
        return 1
    except APIError as exc:
        raise SystemExit(f"request_svm_capture failed: {exc}") from exc

    _describe_details(fresh, "request_svm_capture result")
    Path("svm_fresh.jpg").write_bytes(fresh.image_bytes)
    print("  saved: svm_fresh.jpg")

    if latest.captured_at and fresh.captured_at:
        if fresh.captured_at <= latest.captured_at:
            print("\nWARNING: captured timestamp did not advance; image may still be cached")
        else:
            print("\nFresh image timestamp is newer than cached image.")

    return 0


if __name__ == "__main__":
    sys.exit(main())

If you run it, please paste the output (with credentials/VIN redacted) so we can confirm the implementation matches the real API behavior.

@ijojog

ijojog commented Jun 24, 2026

Copy link
Copy Markdown

I tested the standalone SVM script against the feature/svm-usa-support branch on my Hyundai USA 2025 Tucson Hybrid.

First I ran cached-only with --skip-capture, and that worked.

Then I ran the full capture test, and it also worked.

Output, with VIN redacted:

Logging in...
Using vehicle: 2025 TUCSON HYBRID (VIN redacted)
Fetching latest cached SVM image...

get_svm_details result
  image size: 177260 bytes
  captured at: 2026-06-19 15:29:03+00:00
  heading: 126
  speed: (0.0, '0')
  door open: {'frontLeft': False, 'frontRight': False, 'backLeft': False, 'backRight': False}
  trunk open: False
  image dimensions: (4472, 720)
  saved: svm_latest.jpg

Triggering fresh SVM capture...
(this may take up to ~120 seconds as the library polls for the new image)

request_svm_capture result
  image size: 167317 bytes
  captured at: 2026-06-24 08:14:41+00:00
  heading: 147
  speed: (0.0, '0')
  door open: {'frontLeft': False, 'frontRight': False, 'backLeft': False, 'backRight': False}
  trunk open: False
  image dimensions: (4472, 720)
  saved: svm_fresh.jpg

Fresh image timestamp is newer than cached image.

Both output files were created:

svm_latest.jpg
svm_fresh.jpg

The fresh image timestamp advanced from:

2026-06-19 15:29:03+00:00

to:

2026-06-24 08:14:41+00:00

So from my live vehicle test:

get_svm_details: works
request_svm_capture: works
fresh image polling: works
decoded JPG bytes save correctly
image dimensions were consistent at 4472 x 720

@blka

blka commented Jun 25, 2026

Copy link
Copy Markdown
Contributor Author

@ijojog thank you for the live validation — results look exactly right.

Confirmed behavior on a Hyundai USA 2025 Tucson Hybrid:

  • get_svm_details returns a valid decoded JPG composite (177 kB) with complete metadata.
  • request_svm_capture(..., acknowledged_warning=True) triggers, polls, and returns a newer image (167 kB).
  • Image dimensions are consistently 4472 × 720.
  • Timestamps advance as expected; heading, door/trunk, and speed fields parse correctly.
  • No DuplicateRequestError or authentication issues occurred during the test.

This gives us confidence the implementation matches the real BlueLink USA API contract captured in #1194. Marking the PR ready for review.

@blka
blka marked this pull request as ready for review June 25, 2026 10:34
@ijojog

ijojog commented Jun 25, 2026

Copy link
Copy Markdown

Great, happy to help validate it live. Everything looked good on my side as well. Thanks for implementing this and for moving the PR forward.

@ijojog

ijojog commented Jun 25, 2026

Copy link
Copy Markdown

Great work — happy to help validate it live. Everything looked correct from my side as well during testing.

Thanks for implementing the SVM / Find My Car support and for including the privacy protections around image and GPS logging. I’m glad the live Hyundai USA Tucson validation helped confirm the API behavior.

Happy to test again when the Home Assistant integration follow-up PR is ready.

@blka

blka commented Jun 25, 2026

Copy link
Copy Markdown
Contributor Author

Added capability detection on top of the SVM implementation. Detection is lazy, cached, and safe: it probes once and returns False on any failure. Only Hyundai BlueLink USA probes; other regions return False via the base class.

@ijojog

ijojog commented Jun 26, 2026

Copy link
Copy Markdown

That sounds good. The lazy cached detection makes sense to me, especially if it avoids extra API calls and safely returns False when unsupported or uncertain.

My Hyundai USA Tucson already passed the live SVM get/capture test on this branch, so I’m happy to re-run the standalone script or test a capability-detection-specific script if you want confirmation from a real vehicle/account.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since all calls are placed via vehicleManager how is this used?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch — you're right. get_svm_details and request_svm_capture should go through VehicleManager like every other API call, not be reached into via manager.api. supports_svm already follows that pattern; the two action methods should too.

I'll add VehicleManager.get_svm_details(vehicle_id) and VehicleManager.request_svm_capture(vehicle_id, acknowledged_warning) wrappers, and switch the HA coordinator to call them so it no longer touches manager.api directly.

username=token.username, password=token.password, pin=token.pin
)

def get_svm_details(self, token: Token, vehicle: Vehicle) -> SVMDetails:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like we never store SVMDetails to vehicle. So this would mean we store outside the library and don't follow same model?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From a user/tester perspective, I think SVM is a little different from normal vehicle state.

For normal state like lock, windows, charge, etc., it makes sense to store/update that on the Vehicle object.

But SVM includes a large JPG image plus sensitive capture metadata, so I can see why it may be safer to return it separately instead of storing the raw image bytes directly on vehicle.

My understanding is that Home Assistant would still need to keep the latest SVM image somewhere so it can be displayed, but that does not necessarily mean it should be stored directly on the Vehicle object.

Maybe the cleaner split is:

Vehicle:
- lightweight support/capability info, such as supports_svm

Library method:
- get_svm_details / request_svm_capture returns SVMDetails with the JPG bytes and metadata

Home Assistant:
- stores the returned image bytes in the camera/image entity state/cache so it can be viewed

So the image can still be shown in HA, but the main Vehicle object does not need to permanently carry a large/private JPG payload.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deliberate — @ijojog nailed the reasoning above. SVM is different from normal vehicle state in three ways:

  • Size: the payload is a ~170 KB JPG composite, not a scalar/enum. Storing it on Vehicle would bloat the object that gets dumped, snapshotted, and logged on every refresh.
  • Privacy: SVMDetails.raw_metadata carries GPS-bearing capture data. We keep that out of Vehicle so it can't leak into state dumps or logs.
  • Lifecycle: SVM is on-demand, not part of the periodic poll. Attaching it to Vehicle during refresh would add an HTTP call to every poll cycle.

So the split is: capability (supports_svm: bool | None) lives on Vehicle so HA can gate entities without a probe per render; the image payload is returned by the method and cached by the consumer. In HA that cache lives on the ImageEntity — the right place for image bytes.

Does that split work for you, or would you rather the library hold the latest SVMDetails (on Vehicle behind a field, or on VehicleManager)?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@blka @cdnninja That split makes sense to me from the user/tester side.

Keeping only supports_svm on Vehicle, routing the calls through VehicleManager, and letting Home Assistant’s ImageEntity cache/display the returned JPG sounds like the cleanest approach.

That avoids putting large/private SVM image data or GPS-bearing metadata into the normal Vehicle state/logging path, while still letting HA display the image when requested.

@blka
blka requested a review from cdnninja June 30, 2026 20:50
@blka
blka force-pushed the feature/svm-usa-support branch from 4d14d57 to f4b2e70 Compare July 1, 2026 07:42
blka added a commit to blka/hyundai_kia_connect_api that referenced this pull request Jul 27, 2026
… drift

Replay onto upstream/master (44 commits ahead of original base):
- supports_svm: bool | None = None  (SVM PR Hyundai-Kia-Connect#1203)
- battery_auxiliary_fail_warning_is_on, drive_mode, oil_level_warning_is_on
- tire_pressure_{fl,fr,rl,rr} + _unit, tire_pressure_unit  (upstream Hyundai-Kia-Connect#1218/Hyundai-Kia-Connect#1234/#1796)

Purely additive (122 insertions, 0 deletions); all new fields default None.
@blka
blka force-pushed the feature/svm-usa-support branch from f4b2e70 to 2902948 Compare July 27, 2026 12:43
@blka

blka commented Jul 27, 2026

Copy link
Copy Markdown
Contributor Author

@cdnninja Rebased this onto the current master (44 commits resolved; only conflict was an exceptions import union in HyundaiBlueLinkApiUSA.py — kept both your ServiceTemporaryUnavailable and the SVM additions). Per your earlier feedback, the VehicleManager wrappers (supports_svm, get_svm_details, request_svm_capture) are in place, so HA no longer reaches into manager.api. 456 tests pass, ruff clean. Could you take another look when you get a chance?

blka added 4 commits July 29, 2026 15:17
…ppers

Mirrors the existing supports_svm wrapper so consumers do not reach into
manager.api directly. Matches the lock/climate action-method pattern
(thin delegation, no exception swallowing — action errors propagate).
… drift

Replay onto upstream/master (44 commits ahead of original base):
- supports_svm: bool | None = None  (SVM PR Hyundai-Kia-Connect#1203)
- battery_auxiliary_fail_warning_is_on, drive_mode, oil_level_warning_is_on
- tire_pressure_{fl,fr,rl,rr} + _unit, tire_pressure_unit  (upstream Hyundai-Kia-Connect#1218/Hyundai-Kia-Connect#1234/#1796)

Purely additive (122 insertions, 0 deletions); all new fields default None.
.ruff.toml (target-version = "py310") was accidentally introduced in
b09079e (feat(svm): add SVMDetails dataclass). It does not exist on
upstream/master and silently overrode the project's pyproject.toml
[tool.ruff] target-version = "py312" (set in Hyundai-Kia-Connect#1216 when the Python
floor was bumped to 3.12). ruff precedence: .ruff.toml > pyproject.toml.

Removing it restores the correct py312 target. ruff check + format
still clean under py312; no code changes needed.
…napshot

Complementary refresh — fixture added in Hyundai-Kia-Connect#1254 (after the SVM branch's
snapshot regen) needs the supports_svm field introduced by this PR.
@blka
blka force-pushed the feature/svm-usa-support branch from 23c2150 to 33e24c4 Compare July 29, 2026 13:32
Comment thread hyundai_kia_connect_api/ApiImpl.py Outdated
"request_svm_capture is not implemented for this region"
)

def supports_svm(self, token: Token, vehicle: Vehicle) -> bool:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't most supports items sit within the car?

supports_window_control: bool = None
supports_valet_mode: bool = None

Any reason this one is exposed here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point — this was a deviation. supports_svm was a probe method (GET getSVMDetails, check image_bytes) to get per-vehicle precision, but it does not match the library capability convention. supports_window_control and supports_valet_mode are per-region class attributes on the region API, stamped onto Vehicle by VehicleManager.initialize_vehicles with no API call (Vehicle.py L147-L148).

I have aligned supports_svm to the same pattern:

  • ApiImpl.supports_svm = False (class attribute)
  • HyundaiBlueLinkApiUSA.supports_svm = True (class attribute)
  • VehicleManager.initialize_vehicles stamps vehicle.supports_svm = self.api.supports_svm

The probe method, the base stub, and the VehicleManager.supports_svm(vehicle_id) wrapper are all removed. get_svm_details / request_svm_capture stay — those are the actual image fetch, not capability.

Tradeoff: capability is now per-region, not per-vehicle. Models without SVM hardware will show the entity and the capture will fail at runtime — same behavior as supports_window_control today. @ijojog the capability flag now lives on vehicle.supports_svm as you suggested.

else:
_LOGGER.debug(f"{DOMAIN} - Vehicle Disabled, skipping.")

def supports_svm(self, vehicle_id: str) -> bool:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a new approach over the client using "vehicle.is_XXX_supported" Why is that?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cdnninja @blka From my user/tester perspective, I’m fine with whichever pattern matches the library best.

The important part for me is just that Home Assistant can reliably know whether my vehicle supports SVM before showing the image/capture entities.

If the existing library pattern is vehicle.is_XXX_supported / a support field on Vehicle, then it makes sense to me to follow that for SVM as well, especially since supports_svm is lightweight capability info and not the actual image payload.

I still agree the actual SVMDetails / JPG bytes should stay out of the normal Vehicle state, but the capability flag itself living on Vehicle sounds reasonable if that matches the existing design.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right — the VehicleManager.supports_svm(vehicle_id) wrapper is gone. Same change as in the ApiImpl thread above: supports_svm is now a per-region class attribute (ApiImpl=False, HyundaiBlueLinkApiUSA=True), stamped onto vehicle.supports_svm by VehicleManager.initialize_vehicles — exactly like supports_window_control / supports_valet_mode. Consumers read vehicle.supports_svm directly; no probe, no extra API call, no wrapper. @ijojog the capability flag now lives on vehicle.supports_svm as you suggested; the image payload (SVMDetails) still stays off Vehicle.

Per cdnninja review (2026-08-06): supports_svm was a probe method on
VehicleManager/ApiImpl (GET getSVMDetails, check image_bytes), deviating
from the library's capability convention. supports_window_control and
supports_valet_mode are per-region class attributes on the region API,
stamped onto Vehicle by VehicleManager.initialize_vehicles — no API call.

Align supports_svm to the same pattern:
- ApiImpl: class attr supports_svm = False (was a probe stub method)
- HyundaiBlueLinkApiUSA: class attr supports_svm = True (was a probe method)
- VehicleManager: stamp vehicle.supports_svm = api.supports_svm in
  initialize_vehicles; drop the supports_svm(vehicle_id) wrapper
- Vehicle.supports_svm field unchanged (canonical source, now stamped)

Tradeoff: capability is per-region, not per-vehicle. Models without SVM
hardware will show the entity; capture fails at runtime — same as
supports_window_control today. ijojog (tester) accepted flag-on-Vehicle.

Also fix latent ruff violations exposed by removing .ruff.toml (prev
commit, which unmasked pyproject.toml [tool.ruff] py312 rule set):
- I001 import sort (ApiImpl, VehicleManager, us_svm_test)
- PYI041 svm._parse_float: int | float -> float
- PIE790 SafetyAcknowledgmentError unnecessary pass
- UP017 dt.timezone.utc -> dt.UTC (tests)
- SIM117 collapse nested with (tests)
- TRY004 noqa on _FakeResponse.json ValueError (JSONDecodeError semantic)

Tests: drop 10 probe tests, add 3 class-attr/stamp tests. 450 pass, ruff clean.
return result


def parse_svm_response(response: dict, timezone: dt.timezone) -> SVMDetails:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks specific to the USA API? If so should it be in the API? Same question goes for a few of these other methods.

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.

Add SVM / Find My Car support for Hyundai BlueLink USA

3 participants