Skip to content

willbeeching/ha-jlr-incontrol

Repository files navigation

Jaguar Land Rover InControl for Home Assistant

CI GitHub Release License: MIT hacs_badge vibe-coded Buy Me A Coffee

Get your Jaguar or Land Rover into Home Assistant. Fuel level, doors, windows, tyre pressures, where you parked it, and (if you want) remote lock and climate control. All you need is the email and password you use for the InControl app.

There's no third-party cloud in the middle and nothing to plug into the car. The integration talks to JLR's own backend, so it runs anywhere Home Assistant does.

Warning

Early release, and AI-assisted. I built this by reverse-engineering an undocumented API, with a lot of help from AI coding tools. Expect rough edges. The read-only stuff (sensors, location) is the most reliable part; remote commands may behave differently between models. Use at your own risk, and if something misbehaves, please open an issue.

Community-tested so far (see issue #1):

Vehicle Powertrain Year
Jaguar I-PACE BEV 2019
Jaguar I-PACE BEV 2021
Range Rover Sport PHEV
Discovery Sport PHEV 2025
Defender ICE 2022
Range Rover ICE 2022
Range Rover (L405) ICE 2019

ICE 2022 models remain the best-tested for remote commands. BEV and PHEV support is newer but early community reports are positive — ECC preconditioning is now confirmed working on the I-PACE (see issue #3). VHS refresh and charge control are implemented from native-app API docs and may still need tweaks on the webview backend — please report errors.

What you get

  • Live vehicle status: fuel level and range, odometer, service/AdBlue distance, tyre pressures, 12V battery, coolant temperature, and a fair bit more.
  • BEV support: battery SoC, electric range, charging status, time to full, and charge-now control. ICE-only sensors (fuel level, coolant temp, combined range) are automatically hidden on pure electric vehicles.
  • Every door's open/closed and lock state, all four windows, the sunroof, theft alarm status, and warnings for fluids and service as binary sensors.
  • A GPS device_tracker so you can see where the car is, along with heading, speed, and when it last phoned home.
  • If you provide your vehicle PIN: remote lock, honk & flash, and alarm off.
  • Climate: ICE/PHEV uses remote engine start (REON/REOFF) with a single heat/cool mode — set the target temperature and the car decides whether to heat or cool (15.5 °C is LO on the car's dial, 28.5 °C is HI). BEVs use electric preconditioning (ECC) with a target temperature — no PIN required for ECC.
  • Update from vehicle button (VHS) to force the car to report fresh status, plus a cheap Refresh button that re-polls the server cache.
  • Force charge on / off buttons for BEVs, with a Charge now setting sensor showing the live override state (DEFAULT / FORCE_ON / FORCE_OFF).
  • All info sensor (disabled by default) exposing the full flattened status dict as attributes.
  • Diagnostics download for troubleshooting (VIN/position redacted).
  • Configurable distance and pressure unit overrides in integration options.
  • Got more than one car on the account? They all show up automatically.

Requirements

  • Home Assistant 2024.4 or newer
  • An InControl account with your vehicle(s) added to it
  • Your account email and password
  • Your vehicle security PIN for lock, honk & flash, alarm off, and charge control. BEV climate (ECC) works without a PIN.

Installation

HACS (recommended)

  1. In HACS, open Custom repositories and add this repo with category Integration.
  2. Install Jaguar Land Rover InControl.
  3. Restart Home Assistant.

Manual

Copy custom_components/jlr_incontrol/ into your Home Assistant config/custom_components/ folder and restart.

Setup

  1. Go to Settings → Devices & Services → Add Integration and search for Jaguar Land Rover InControl.
  2. Enter your InControl email and password.
  3. Optionally enter your vehicle PIN. If you leave it blank you get monitoring only (plus BEV climate if you have an electric vehicle). You can add the PIN later by reconfiguring the entry.

Each vehicle shows up as a device with its sensors, binary sensors, and control entities.

Options

Under Configure on the integration entry you can override distance units (miles / km) and pressure units (kPa / bar / psi). Leave as "Use Home Assistant default" to let HA convert automatically.

HACS beta releases: enable Show beta versions on the custom repository in HACS (⋮ menu → Show beta versions) to pick a tagged release (e.g. v1.0.0-beta.4) instead of tracking the default branch.

How it works

Login is a standard password grant, and the integration then reads status and sends commands through the same webview API that JLR's own apps use, with a registered device id. Your credentials, device id, user id, and vehicle info are fetched at setup and stored in your own Home Assistant config entry. None of it goes anywhere else.

Polling is adaptive, to keep the load on JLR's servers low (being a polite client is the best way to keep an unofficial integration alive): every 5 minutes while something is happening — the car is plugged in or charging, the climate is running, values are changing (e.g. while driving), or you've recently pressed a button or sent a command — and every 20 minutes once the car has been quiet for half an hour. Vehicle attributes (make/model/capabilities) are cached for a day rather than re-fetched on every poll. Tokens are long-lived and refresh automatically, so you shouldn't need to log in again.

A couple of things worth knowing:

  • The status you see is whatever the car last reported to JLR's servers. Use Update from vehicle (VHS) to wake the car and push fresh data, or Refresh to re-fetch the cached copy from the backend. Verified live: VHS refreshes the core/health block (doors, 12V battery, diagnostics). EV charge data (SoC, charging state) comes from a separate vehicle subsystem that VHS doesn't touch, so on a BEV a VHS can "succeed" without those values changing.
  • The last_updated timestamp reflects when the car last reported position/status to JLR — it may lag behind individual values like SoC during charging.
  • Locked and alarm-armed are independent states: a car can be locked with the alarm off. A remote lock command both locks and arms. Alarm state changes reach the backend in ~30 seconds.
  • Remote commands wake the car, so they take a few seconds. The integration waits for the vehicle to confirm before reporting success or failure.
  • ECC preconditioning, VHS refresh, and charge control use endpoints documented from the native-app API. They may need media-type tweaks on the webview edge — please report errors.

Why there's no trip / journey data

Short version: JLR turned it off. The /trips endpoint still exists on the webview edge (it negotiates media types — a wrong Accept returns a proper 406), but with the correct triplist-v2 media type the legacy backend behind it never answers and eventually returns a 504 Gateway Timeout (verified with waits of 70+ seconds). Two other signals confirm it's gone for good: the modern app/webview JS bundle contains no trip endpoints at all, and the old direct /if9/jlr/ path that community integrations used for trips is now behind JLR's Approov attestation wall. A last-trip sensor would just sit there timing out and slow every refresh down, so this integration deliberately doesn't have one. If JLR ever resurfaces journeys in their API, it can come back.

The legacy owner web portal (incontrol.jaguar.com) was also checked as an alternative source: it still has a Journeys feature, but it lives behind its own web SSO cookie login (a separate auth world from the token flow this integration uses), and its trips backend is the same service that times out. Not a viable path either.

Why there's no Guardian Mode

Half-supported by the backend, not by our path to it. The Guardian endpoints (gm/status, gm/alarms) exist and respond quickly, and PIN authentication for the GM service works — but the webview edge this integration relies on doesn't expose usable Guardian reads: the endpoints are POST-only there and reject every content type, the settings paths 404, and the webview app's own code contains no Guardian feature at all. The native app does Guardian over its Approov-attested path, which we can't use. Toggling Guardian Mode in the JLR app also has no effect on any status key this integration can see, so there's nothing to sense either.

Disclaimer

This is an unofficial community project with no affiliation to, or endorsement from, Jaguar Land Rover. It relies on an undocumented API that JLR could change or block tomorrow, which would break things without warning. It was developed with AI assistance, it's an early release, it comes with no warranty, and remote commands may behave differently between models. Use it with your own account and vehicles, at your own risk. There are more technical notes and a data model write-up in docs/ if you're curious.

Support

This was reverse-engineered and vibe-coded over many late nights, and the AI tokens don't pay for themselves. If this integration ever saved you a trip outside to check whether you locked the car, consider buying me some AI tokens ☕🤖. Entirely optional — bug reports and stars are appreciated just as much.

About

Unofficial Home Assistant integration for Jaguar Land Rover InControl — live vehicle status, location, and remote controls.

Topics

Resources

License

Stars

14 stars

Watchers

7 watching

Forks

Contributors

Languages