{"id":22221101,"url":"https://github.com/davesag/node-tesla-api","last_synced_at":"2025-07-27T16:31:05.749Z","repository":{"id":36965273,"uuid":"251454949","full_name":"davesag/node-tesla-api","owner":"davesag","description":"A modern nodeJS implementation of the (unofficial) Tesla API","archived":false,"fork":false,"pushed_at":"2024-11-27T07:43:10.000Z","size":1875,"stargazers_count":13,"open_issues_count":16,"forks_count":0,"subscribers_count":4,"default_branch":"develop","last_synced_at":"2024-11-27T08:30:08.631Z","etag":null,"topics":["api-client","nodejs","tesla","tesla-api"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/davesag.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["davesag"]}},"created_at":"2020-03-30T23:49:51.000Z","updated_at":"2024-03-30T06:16:59.000Z","dependencies_parsed_at":"2023-02-19T05:05:16.533Z","dependency_job_id":"800b72f9-5a1d-4cc2-b871-af5b599d970b","html_url":"https://github.com/davesag/node-tesla-api","commit_stats":{"total_commits":235,"total_committers":2,"mean_commits":117.5,"dds":"0.012765957446808529","last_synced_commit":"6bd7eb28f94704e18fc27903127ca581b8fd42fb"},"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davesag%2Fnode-tesla-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davesag%2Fnode-tesla-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davesag%2Fnode-tesla-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davesag%2Fnode-tesla-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/davesag","download_url":"https://codeload.github.com/davesag/node-tesla-api/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":227817166,"owners_count":17824199,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api-client","nodejs","tesla","tesla-api"],"created_at":"2024-12-02T23:12:13.303Z","updated_at":"2024-12-02T23:12:14.063Z","avatar_url":"https://github.com/davesag.png","language":"JavaScript","funding_links":["https://github.com/sponsors/davesag"],"categories":[],"sub_categories":[],"readme":"# node-tesla-api\n\nA modern NodeJS implementation of the [(unofficial) Tesla API](https://tesla-api.timdorr.com).\n\n[![NPM](https://nodei.co/npm/node-tesla-api.png)](https://nodei.co/npm/node-tesla-api/)\n\nUnder development: _features outlined below may not be final_.\n\n## It's borked\n\nTesla changed their Auth process so I need to update this API. Right now it does not work.\n\nRef: [`timdorr/tesla-api/issues/260`](https://github.com/timdorr/tesla-api/issues/260)\n\n## Usage\n\n```sh\nnpm i node-tesla-api\n```\n\nI'm only focussing on the `oauth`, `vehicles`, and `logs` parts of the Tesla API for now.\n\nThe API follows the commands outlined in the [(unofficial) Tesla API](https://tesla-api.timdorr.com), but uses camelCase instead of underscores.\n\n**You'll need to have access to a Tesla**, and have a valid Tesla username and password to make use of this API.\n\nPlease feel free to use [my Tesla referral code](https://ts.la/david60377) if you buy a Tesla - we both get some free charging that way.\n\nMy code is: [`david60377`](https://ts.la/david60377)\n\n### Example\n\n```js\nconst { oauth, vehicles } = require('node-tesla-api')\n\nconst sleep = async delay =\u003e new Promise(resolve =\u003e setTimeout(resolve, delay))\n\nconst wakeCar = async ({ id, token, retry = 0, maxRetries = 3 }) =\u003e {\n  if (retry === maxRetries) return\n\n  const {\n    response: { state }\n  } = await vehicles.vehicle({ id, token })\n  if (state === 'online') return\n\n  await vehicles.wake({ id, token })\n  await sleep(DELAY)\n  // try again\n  await wakeCar({ id, token, retry: retry + 1, maxRetries })\n}\n\nconst start = async (email, password) =\u003e {\n  const { accessToken: token } = await oauth.token({\n    email,\n    password,\n    // These values are an open secret.\n    // See https://tesla-api.timdorr.com for the latest values.\n    clientSecret: 'get-me-from-pastebin',\n    clientId: 'also-get-me-from-pastebin'\n  })\n  console.log('token', token)\n\n  const { response: cars } = await vehicles.list({ token })\n  console.log('cars', cars)\n\n  const { idS: id } = cars.find(car =\u003e car.displayName === 'Terry')\n  await wakeCar({ id, token })\n\n  const { response: state } = await vehicles.vehicleState({ id, token })\n  console.log('state', JSON.stringify(state, null, 2))\n}\n\nstart('your-tesla@account.email', 'Y0uRP@55w0rd').catch(err =\u003e {\n  console.error(err)\n})\n```\n\n## API\n\nThe API is broken down into\n\n- `oauth` — you provide your username and password and get back a `token`.\n- `vehicles` - using the `token` you interact with your vehicles\n- `logs` - using the `token` you can perform various diagnostics, but only if the token has the correct embedded permissions.\n\n### `oauth`\n\nControls how you obtain, refresh and revoke tokens.\n\n```js\nconst { oauth } = require('node-tesla-api')\n```\n\n---\n\n#### `token`\n\nReturns the `accessToken` you will need to invoke the other api functions.\n\n```js\nconst { accessToken, refreshToken, tokenType, createdAt, expiresIn } = await oauth.token({\n  email: 'your-tesla@account.email',\n  password: 'your-password',\n  clientSecret: 'get-me-from-pastebin',\n  clientId: 'also-get-me-from-pastebin'\n})\n```\n\n- On `timdorr`: [`post-oauth-token-grant_type-password`](https://tesla-api.timdorr.com/api-basics/authentication#post-oauth-token-grant_type-password)\n- On `teslaapi`: [`get-access-token`](https://www.teslaapi.io/authentication/oauth#get-access-token)\n\n---\n\n#### `refresh`\n\nReturns a _refreshed_ `accessToken`. Use this if your original token has expired.\n\n```js\nconst { accessToken, refreshToken, tokenType, createdAt, expiresIn } = await oauth.refresh({\n  refreshToken: 'the refresh token you got back from the `token` function',\n  clientSecret: 'get-me-from-pastebin',\n  clientId: 'also-get-me-from-pastebin'\n})\n```\n\n- On `timdorr`: [`post-oauth-token-grant_type-refresh_token`](https://tesla-api.timdorr.com/api-basics/authentication#post-oauth-token-grant_type-refresh_token)\n- On `teslaapi`: [`get-access-token`](https://www.teslaapi.io/authentication/oauth#get-access-token)\n\n---\n\n#### `revoke`\n\nRevokes an `accessToken`. Use this to log the user out.\n\n```js\nawait oauth.revoke({ token: 'the access token you got back from the `token` function' })\n```\n\n- On `timdorr`: Not mentioned\n- On `teslaapi`: [`revoke-access-token`](https://www.teslaapi.io/authentication/oauth#revoke-access-token)\n\n---\n\n### `vehicles`\n\nUsing the accessToken issued above you use the `vehicles` functions to interact with your car.\n\n```js\nconst { vehicles } = require('node-tesla-api')\n```\n\n---\n\n#### `list`\n\nGet a list of your vehicles.\n\n```js\nconst { response: cars } = await vehicles.list({ token })\n\nconst {\n  id, // don't use this integer version as the number overflows\n  vehicleId, // a number, unsure what it's used for\n  vin, // a string\n  displayName, // a string\n  optionCodes, // a string of comma separated codes\n  color, // not sure - usually null\n  accessType, // e.g. 'OWNER'\n  tokens, // an array of tokens\n  state, // \"online\" if the car is online\n  inService, // boolean\n  idS, // use this string version of the id instead of id\n  calendarEnabled, // boolean\n  apiVersion, // a number, e.g. 10 right now.\n  backseatToken, // unsure what this is\n  backseatTokenUpdatedAt // timestamp or null\n  vehicleConfig, // e.g. null\n} = cars[0]\n```\n\n- On `timdorr`: [`get-api-1-vehicles`](https://tesla-api.timdorr.com/api-basics/vehicles#get-api-1-vehicles)\n- On `teslaapi`: [`vehicles`](https://www.teslaapi.io/vehicles/list#vehicles)\n\n---\n\n#### `vehicle`\n\nGet the basic details of a specific vehicle.\n\n```js\n// using the `idS` field returned from `vehicles.list`, not the `id`, or `vehicleId`.\n// and the token from `oauth.token`\nconst {\n  id, // don't use this integer version as the number overflows\n  vehicleId, // a number, unsure what it's used for\n  vin, // a string\n  displayName, // a string\n  optionCodes, // a string of comma separated codes\n  color, // not sure - usually null\n  accessType, // e.g. 'OWNER'\n  tokens, // an array of two tokens\n  state, // \"online\" if the car is online\n  inService, // boolean\n  idS, // use this string version of the id instead of id\n  calendarEnabled, // boolean\n  apiVersion, // a number, e.g. 10 right now.\n  backseatToken, // unsure what this is\n  backseatTokenUpdatedAt // timestamp or null\n  vehicleConfig, // e.g. null\n} = await vehicles.vehicle({ id, token })\n```\n\n- On `timdorr`: [`get-api-1-vehicles-id`](https://tesla-api.timdorr.com/api-basics/vehicles#get-api-1-vehicles-id)\n- On `teslaapi`: [`vehicle`](https://www.teslaapi.io/vehicles/list#vehicle)\n\nThe keen observer will note that this is the same data as returned in the vehicle list response.\n\n---\n\n#### `wake`\n\nWhen you first get the details of your car, you need to check the `state` to see if it's `'online'` or not.\n\nIf the car's `state` is `'asleep'` or otherwise not `'online'` then you need to wake it up before you can do anything with it.\n\n**Note** You might also want to check to see if the car is `inService` (`true` or `false`) if you are going to do something like move it, or start it.\n\nTo wake up the car you send it a `wake` command as follows:\n\n```js\nawait vehicles.wake({ id, token })\n```\n\nNow just because you told the car to wake, doesn't mean that the car will actually wake up. Sometimes your car can go into a deep-sleep mode, or it might even be off, or disconnected from the network.\n\nYou need to keep checking the `state` and reissuing the `wake` command until either the car really wakes up, or decide to stop trying.\n\n```js\n// Check the `state` of the car recursively, trying three times to wake it up.\nconst wakeCar = async ({ id, token, retry = 0, maxRetries = 3 }) =\u003e {\n  if (retry === maxRetries) return\n\n  const {\n    response: { state }\n  } = await vehicles.vehicle({ id, token })\n  if (state === 'online') return\n\n  await vehicles.wake({ id, token })\n  await sleep(DELAY)\n  // try again\n  await wakeCar({ id, token, retry: retry + 1, maxRetries })\n}\n```\n\nThen you can just call\n\n```js\nawait wakeCar({ id, token })\n```\n\n**ToDo**: Compose a high-level API that simplifies the use of this low-level API wrapper. (See [issues/28](https://github.com/davesag/node-tesla-api/issues/28))\n\n- On `timdorr`: [`post-api-1-vehicles-id-wake_up`](https://tesla-api.timdorr.com/vehicle/commands/wake#post-api-1-vehicles-id-wake_up)\n- On `teslaapi`: [`wake-up`](https://www.teslaapi.io/vehicles/commands#wake-up)\n\n---\n\n#### `vehicleData`\n\nNow you know how to wake your car, let's take a look at the full set of car data.\n\n```js\nconst {\n  response: {\n    id, // don't use this.\n    userId,\n    vehicleId, // or this\n    vin,\n    displayName, // TODO: Is this ever different to `vehicleName`?\n    optionCodes,\n    color,\n    accessType, // e.g. \"OWNER\"  TODO: find out these values.\n    tokens, // array of two small strings\n    state, // should be \"online\",\n    inService, // boolean,\n    idS, // use this instead of `id`\n    calendarEnabled, // boolean\n    apiVersion, // e.g. 10\n    backseatToken, // TODO: find out what this is for\n    backseatTokenUpdatedAt, // TODO: find out what this is for\n    vehicleConfig: {\n      canAcceptNavigationRequests, // boolean\n      canActuateTrunks, // boolean\n      carSpecialType, // e.g. \"base\" TODO: find out these values.\n      carType, // mine is a \"model3\"  TODO: find out these values.\n      chargePortType, // mine is \"CCS\"  TODO: find out these values.\n      eceRestrictions, // boolean\n      euVehicle, // boolean (e.g. true but I am in AU)\n      exteriorColor, // mine is \"MidnightSilver\"  TODO: find out these values.\n      hasAirSuspension, // boolean\n      hasLudicrousMode, // boolean\n      keyVersion, // e.g. 2\n      motorizedChargePort, // boolean\n      plg, // boolean (e.g. false)\n      rearSeatHeaters, // e.g. 1 - I have rear seat heaters\n      rearSeatType, // e.g. null\n      rhd, // right hand drive? (e.g. true)\n      roofColor, // e.g. \"Glass\"  TODO: find out these values.\n      seatType, // e.g. null\n      spoilerType, // e.g. \"None\"\n      sunRoofInstalled, // e.g. null,\n      thirdRowSeats, // e.g. \"\u003cinvalid\u003e\",  TODO: find out these values.\n      timestamp: vcTimestamp, // unix epoch timestamp\n      useRangeBadging, // e.g. true,\n      wheelType, // e.g. \"Pinwheel18\"  TODO: find out these values.\n    },\n    chargeState: {\n      batteryHeaterOn, // boolean\n      batteryLevel, // integer percentage\n      batteryRange, // floating point value using imperial units (miles)\n      chargeCurrentRequest, // how many amps the car wants (e.g. 8)\n      chargeCurrentRequestMax,  // how many amps the car can have (e.g. 8)\n      chargeEnableRequest, // boolean\n      chargeEnergyAdded, // floating point number (e.g 10.15)\n      chargeLimitSoc, // integer percentage (e.g 94)\n      chargeLimitSocMax,  // integer percentage (e.g 100)\n      chargeLimitSocMin,   // integer percentage (e.g 50)\n      chargeLimitSocStd,  // integer percentage (e.g 90)\n      chargeMilesAddedIdeal,   // floating point number (e.g 41.5)\n      chargeMilesAddedRated,   // floating point number (e.g 41.5)\n      chargePortColdWeatherMode, // boolean\n      chargePortDoorOpen, // boolean\n      chargePortLatch, // e.g \"Engaged\"  TODO: find out these values.\n      chargeRate, // a number TODO: check these values when charging the car\n      chargeToMaxRange, // boolean\n      chargerActualCurrent, // a number e.g 0   TODO: check these values when charging the car\n      chargerPhases, // 1 = single, 3 = three  TODO: is there such a thing as 2 phase power?\n      chargerPilotCurrent, // something else measured in amps (e.g. 8)\n      chargerPower, // a number (TODO: check these values when charging the car)\n      chargerVoltage, // an integer (e.g 2)\n      chargingState, // e.g. \"Stopped\"  TODO: find out these values.\n      connChargeCable, // e.g. \"IEC\"  TODO: find out these values.\n      estBatteryRange, // floating point value using imperial units (miles) (e.g. 273.36)\n      fastChargerBrand, // e.g. \"\u003cinvalid\u003e\"\n      fastChargerPresent, // boolean\n      fastChargerType, // e.g. \"MCSingleWireCAN\"  TODO: find out these values.\n      idealBatteryRange,// floating point value using imperial units (miles) (e.g. 281.16)\n      managedChargingActive, // boolean\n      managedChargingStartTime, // a timestamp or null\n      managedChargingUserCanceled, // boolean\n      maxRangeChargeCounter, // TODO: maybe how the car knows to warn you about overcharging.\n      minutesToFullCharge, // integer count (e.g 0)\n      notEnoughPowerToHeat: null, // e.g. null  TODO: find out these values.\n      scheduledChargingPending, // boolean\n      scheduledChargingStartTime, //  unix epoch timestamp\n      timeToFullCharge, // integer count (e.g 0)\n      timestamp: chsTimestamp,//  unix epoch timestamp\n      tripCharging, // boolean\n      usableBatteryLevel, // integer percentage (e.g 93)\n      userChargeEnableRequest // e.g. null  TODO: find out these values.\n    },\n    climateState: {\n      batteryHeater, // boolean\n      batteryHeaterNoPower, // e.g. null  TODO: find out these values.\n      climateKeeperMode, // e.g \"off\"  TODO: find out these values.\n      defrostMode, // e.g. 0.  TODO: find out these values.\n      driverTempSetting, // e.g. 22 (uses GUI setting `guiTemperatureUnits`)\n      fanStatus, // e.g. 0.  TODO: find out these values.\n      insideTemp, // e.g. 16.2 (uses GUI setting `guiTemperatureUnits`)\n      isAutoConditioningOn, // boolean\n      isClimateOn, // boolean\n      isFrontDefrosterOn, // boolean\n      isPreconditioning, // boolean\n      isRearDefrosterOn, // boolean\n      leftTempDirection, // e.g. 326 - range is 0 to 360 presumably.\n      maxAvailTemp, // e.g. 28 (uses GUI setting `guiTemperatureUnits`)\n      minAvailTemp, // e.g. 15 (uses GUI setting `guiTemperatureUnits`)\n      outsideTemp, // e.g. 15.5 (uses GUI setting `guiTemperatureUnits`)\n      passengerTempSetting, // e.g. 22 (uses GUI setting `guiTemperatureUnits`)\n      remoteHeaterControlEnabled, // boolean\n      rightTempDirection // e.g. 326 - range is 0 to 360 presumably.\n      seatHeaterLeft, // 0 = off, else 1, 2, or 3\n      seatHeaterRearCenter, // 0 = off, else 1, 2, or 3\n      seatHeaterRearLeft, // 0 = off, else 1, 2, or 3\n      seatHeaterRearRight, // 0 = off, else 1, 2, or 3\n      seatHeaterRight, // 0 = off, else 1, 2, or 3\n      sideMirrorHeaters, // boolean\n      timestamp: clsTimestamp, // unix epoch timestamp again\n      wiperBladeHeater: false\n    },\n    driveState: {\n      gpsAsOf, // unix epoch timestamp\n      heading, // e.g. 340 0 to 360 integer degrees\n      latitude, // e.g. -30.336537\n      longitude, // e.g. 141.145116,\n      nativeLatitude, // e.g. -30.336537  TODO: what's this all about?\n      nativeLocationSupported, // e.g. 1  TODO: what's this all about?\n      nativeLongitude, // e.g. 141.145116  TODO: what's this all about?\n      nativeType, // e.g. \"wgs\"  TODO: get acceptable values for this\n      power, // e.g. 0  TODO: get acceptable values for this\n      shiftState, // e.g. null  TODO: get acceptable values for this\n      speed, // e.g. null  TODO: find out the units for this but my guess is imperial units (mph)\n      timestamp: dsTimestamp, // e.g. 1600552117638\n    },\n    guiSettings: {\n      gui24HourTime, // boolean\n      guiChargeRateUnits, // e.g. \"kW\"  TODO: get acceptable values for this\n      guiDistanceUnits, // e.g. \"km/hr\"  TODO: get acceptable values for this\n      guiRangeDisplay, // e.g. \"Rated\"  TODO: get acceptable values for this\n      guiTemperatureUnits, // e.g. \"C\"  TODO: get acceptable values for this\n      showRangeUnits, // boolean\n      timestamp: gsTimestamp, // unix epoch timestamp\n    },\n    vehicleState: {\n      apiVersion, // e.g. 10,\n      autoparkStateV2, // e.g. \"standby\"  TODO: get acceptable values for this\n      autoparkStyle, // e.g. \"standard\", \"dead_man\"  TODO: get acceptable values for this\n      calendarSupported, // boolean\n      carVersion, // e.g. \"2020.36.10 010e3e5a2863\",\n      centerDisplayState, // e.g. 0 = off, 2 = on, 3 = charging screen, 7 = sentry mode, 8 = dog mode\n      df, // e.g. 0 (driver-side front tyre/someone sitting?) TODO: get acceptable values\n      dr, // e.g. 0 (driver-side rear tyre/someone sitting?) TODO: get acceptable values\n      fdWindow, // e.g. 0 (front driver-side window)  TODO: get acceptable values\n      fpWindow, // e.g. 0 (front passenger-side window)  TODO: get acceptable values\n      ft, // e.g. 0 (front trunk) TODO get acceptable values\n      isUserPresent, // boolean\n      lastAutoparkError, // e.g. \"no_error\",\n      locked, // boolean\n      mediaState: {\n        remoteControlEnabled  // boolean\n      },\n      notificationsSupported, // boolean\n      odometer, // e.g 16686.68661 always in imperial units (miles)\n      parsedCalendarSupported, // boolean\n      pf, // e.g. 0 (passenger-side front tyre/someone sitting?) TODO: get acceptable values\n      pr, // e.g. 0 (passenger-side rear tyre/someone sitting?) TODO: get acceptable values\n      rdWindow, // e.g. 0 (rear driver-side window)  TODO: get acceptable values\n      remoteStart, // boolean\n      remoteStartEnabled, // boolean\n      remoteStartSupported, // boolean\n      rpWindow, // e.g. 0 TODO no idea what this is (driver-side front)\n      rt, // e.g. 0 (rear trunk) TODO get acceptable values\n      sentryMode, // boolean\n      sentryModeAvailable, // boolean\n      smartSummonAvailable, // boolean\n      softwareUpdate: {\n        downloadPerc, // 0 if not downloading\n        expectedDurationSec, // e.g. 2700 but no update downloading\n        installPerc, // 1 if not installing\n        status, // e.g. ''\n        version, // e.g. ''\n      },\n      speedLimitMode: {\n        active, // boolean\n        currentLimitMph, // always in imperial units\n        maxLimitMph, // always in imperial units\n        minLimitMph, // always in imperial units\n        pinCodeSet, // boolean\n      },\n      summonStandbyModeEnabled, // boolean\n      timestamp, // numeric unix epoch time\n      valetMode, // boolean\n      valetPinNeeded, // boolean\n      vehicleName // TODO: is this different to the displayName of the vehicle?\n    }\n} = await vehicles.vehicleState({ id, token })\n```\n\n- On `timdorr`: [`get-api-1-vehicles-id-vehicle_data`](https://tesla-api.timdorr.com/vehicle/state/data#get-api-1-vehicles-id-vehicle_data)\n- On `teslaapi`: [`vehicle-data`](https://www.teslaapi.io/vehicles/state-and-settings#vehicle-data)\n\n---\n\n#### `vehicleState`\n\nThe car's current state (This is the same as the `vehicleState` field in the response to `vehicles.vehicleData()`)\n\n```js\nconst {\n  response: {\n    apiVersion, // e.g. 10\n    autoparkStateV2, // 'standby' or ? (also seeing `autoparkStateV3` in docs)\n    autoparkStyle, // e.g. 'standard', 'dead_man'\n    calendarSupported, // boolean\n    carVersion, // e.g. '2020.36.10 010e3e5a2863'\n    centreDisplayState, // e.g. 0 = off, 2 = on, 3 = charging screen, 7 = sentry mode, 8 = dog mode\n    df, // driver-side front door 0 = closed, non-zero is open.\n    dr, // driver-side rear door 0 = closed, non-zero is open.\n    fdWindow, // e.g. 0 = closed, non-zero is open (front driver-side window) TODO is it a %?\n    fpWindow, // e.g. 0 = closed, non-zero is open (front passenger-side window) TODO is it a %?\n    ft, // front trunk (aka frunk) 0 = closed, non-zero is open.\n    isUserPresent, // boolean\n    lastAutoparkError, // 'no_error'\n    locked, // boolean\n    mediaState: { // see also the `mediaState` command\n      remoteControlEnabled, // e.g. true. boolean\n    },\n    notificationsSupported, // boolean\n    odometer, // NOTE always in miles not metric\n    parsedCalendarSupported, // boolean\n    pf, // passenger-side front door 0 = closed, non-zero is open.\n    pr, // passenger-side rear door 0 = closed, non-zero is open.\n    rdWindow, // e.g. 0 (rear driver-side window)\n    remoteStart, // boolean\n    remoteStartEnabled, // boolean\n    remoteStartSupported, // boolean\n    rpWindow, // e.g. 0 (rear passenger-side window)\n    rt, // rear trunk (aka boot) 0 = closed, non-zero is open.\n    sentryMode, // boolean\n    sentryModeAvailable, // boolean\n    smartSummonAvailable, // boolean\n    softwareUpdate: {\n      downloadPerc, // 0 if not downloading\n      expectedDurationSec, // e.g. 2700 but no update downloading\n      installPerc, // 1 if not installing\n      status, // e.g. ''\n      version, // e.g. ''\n    },\n    speedLimitMode; {\n      active, // boolean\n      currentLimitMph, // always in imperial units\n      maxLimitMph, // always in imperial units\n      minLimitMph, // always in imperial units\n      pinCodeSet, // boolean\n    },\n    summonStandbyModeEnabled, // boolean\n    timestamp, // numeric unix epoch time\n    valetMode, // boolean\n    valetPinNeeded, // boolean\n    vehicleName // TODO: is this different to the displayName of the vehicle?\n  }\n} = await vehicles.vehicleState({ id, token })\n```\n\n- On `timdorr`: [`get-api-1-vehicles-id-data_request-vehicle_state`](https://tesla-api.timdorr.com/vehicle/state/vehiclestate#get-api-1-vehicles-id-data_request-vehicle_state)\n- On `teslaapi`: not listed\n\n---\n\n#### `vehicleConfig`\n\nThe car's configuration (This is the same as the `vehicleConfig` field in the response to `vehicles.vehicleData()`)\n\n```js\nconst {\n  response: {\n    canAcceptNavigationRequests, // boolean\n    canActuateTrunks, // boolean\n    carSpecialType, // e.g. \"base\" TODO: find out these values.\n    carType, // mine is a \"model3\"  TODO: find out these values.\n    chargePortType, // mine is \"CCS\"  TODO: find out these values.\n    eceRestrictions, // boolean\n    euVehicle, // boolean (e.g. true but I am in AU)\n    exteriorColor, // mine is \"MidnightSilver\"  TODO: find out these values.\n    hasAirSuspension, // boolean\n    hasLudicrousMode, // boolean\n    keyVersion, // e.g. 2\n    motorizedChargePort, // boolean\n    plg, // boolean (e.g. false)\n    rearSeatHeaters, // e.g. 1 - I have rear seat heaters\n    rearSeatType, // e.g. null\n    rhd, // right hand drive? (e.g. true)\n    roofColor, // e.g. \"Glass\"  TODO: find out these values.\n    seatType, // e.g. null\n    spoilerType, // e.g. \"None\"\n    sunRoofInstalled, // e.g. null,\n    thirdRowSeats, // e.g. \"\u003cinvalid\u003e\",  TODO: find out these values.\n    timestamp, // unix epoch timestamp\n    useRangeBadging, // e.g. true,\n    wheelType // e.g. \"Pinwheel18\"  TODO: find out these values.\n  }\n} = await vehicles.vehicleConfig({ id, token })\n```\n\n- On `timdorr`: [`get-api-1-vehicles-id-data_request-vehicle_config`](https://tesla-api.timdorr.com/vehicle/state/vehicleconfig#get-api-1-vehicles-id-data_request-vehicle_config)\n- On `teslaapi`: not listed\n\n---\n\n#### `chargeState`\n\nThe car's current charge state. (This is the same as the `chargeState` field in the response to `vehicles.vehicleData()`)\n\n```js\nconst {\n  response: {\n    batteryHeaterOn, // boolean\n    batteryLevel, // integer percentage\n    batteryRange, // floating point value using imperial units (miles)\n    chargeCurrentRequest, // how many amps the car wants (e.g. 8)\n    chargeCurrentRequestMax, // how many amps the car can have (e.g. 8)\n    chargeEnableRequest, // boolean\n    chargeEnergyAdded, // floating point number (e.g 10.15)\n    chargeLimitSoc, // integer percentage (e.g 94)\n    chargeLimitSocMax, // integer percentage (e.g 100)\n    chargeLimitSocMin, // integer percentage (e.g 50)\n    chargeLimitSocStd, // integer percentage (e.g 90)\n    chargeMilesAddedIdeal, // floating point number (e.g 41.5)\n    chargeMilesAddedRated, // floating point number (e.g 41.5)\n    chargePortColdWeatherMode, // boolean\n    chargePortDoorOpen, // boolean\n    chargePortLatch, // e.g \"Engaged\"  TODO: find out these values.\n    chargeRate, // a number (TODO: check these values when charging the car)\n    chargeToMaxRange, // boolean\n    chargerActualCurrent, // a number (TODO: check these values when charging the car)\n    chargerPhases, // 1 = single, 3 = three  TODO: is there such a thing as 2 phase power?\n    chargerPilotCurrent, // something else measured in amps (e.g. 8)\n    chargerPower, // a number (TODO: check these values when charging the car)\n    chargerVoltage, // an integer (e.g 2)\n    chargingState, // e.g. \"Stopped\"  TODO: find out these values.\n    connChargeCable, // e.g. \"IEC\"  TODO: find out these values.\n    estBatteryRange, // floating point value using imperial units (miles) (e.g. 273.36)\n    fastChargerBrand, // e.g. \"\u003cinvalid\u003e\"\n    fastChargerPresent, // boolean\n    fastChargerType, // e.g. \"MCSingleWireCAN\"  TODO: find out these values.\n    idealBatteryRange, // floating point value using imperial units (miles) (e.g. 281.16)\n    managedChargingActive, // boolean\n    managedChargingStartTime, // a timestamp or null\n    managedChargingUserCanceled, // boolean\n    maxRangeChargeCounter, // TODO: maybe how the car knows to warn you about overcharging.\n    minutesToFullCharge, // integer count (e.g 0)\n    notEnoughPowerToHeat: null, // e.g. null  TODO: find out these values.\n    scheduledChargingPending, // boolean\n    scheduledChargingStartTime, //  unix epoch timestamp\n    timeToFullCharge, // integer count (e.g 0)\n    timestamp, //  unix epoch timestamp\n    tripCharging, // boolean\n    usableBatteryLevel, // integer percentage (e.g 93)\n    userChargeEnableRequest // e.g. null  TODO: find out these values.\n  }\n} = await vehicles.chargeState({ id, token })\n```\n\n- On `timdorr`: [`get-api-1-vehicles-id-data_request-charge_state`](https://tesla-api.timdorr.com/vehicle/state/chargestate#get-api-1-vehicles-id-data_request-charge_state)\n- On `teslaapi`: ['charge-state'](https://www.teslaapi.io/vehicles/state-and-settings#charge-state)\n\n---\n\n#### `climateState`\n\nThe car's current climate state. (This is the same as the `climateState` field in the response to `vehicles.vehicleData()`)\n\n```js\nconst {\n  response: {\n    batteryHeater, // boolean\n    batteryHeaterNoPower, // e.g. null  TODO: find out these values.\n    climateKeeperMode, // e.g \"off\"  TODO: find out these values.\n    defrostMode, // e.g. 0.  TODO: find out these values.\n    driverTempSetting, // e.g. 22 (uses GUI setting `guiTemperatureUnits`)\n    fanStatus, // e.g. 0.  TODO: find out these values.\n    insideTemp, // e.g. 16.2 (uses GUI setting `guiTemperatureUnits`)\n    isAutoConditioningOn, // boolean\n    isClimateOn, // boolean\n    isFrontDefrosterOn, // boolean\n    isPreconditioning, // boolean\n    isRearDefrosterOn, // boolean\n    leftTempDirection, // e.g. 326 - range is 0 to 360 presumably.\n    maxAvailTemp, // e.g. 28 (uses GUI setting `guiTemperatureUnits`)\n    minAvailTemp, // e.g. 15 (uses GUI setting `guiTemperatureUnits`)\n    outsideTemp, // e.g. 15.5 (uses GUI setting `guiTemperatureUnits`)\n    passengerTempSetting, // e.g. 22 (uses GUI setting `guiTemperatureUnits`)\n    remoteHeaterControlEnabled, // boolean\n    rightTempDirection // e.g. 326 - range is 0 to 360 presumably.\n    seatHeaterLeft, // 0 = off, else 1, 2, or 3\n    seatHeaterRearCenter, // 0 = off, else 1, 2, or 3\n    seatHeaterRearLeft, // 0 = off, else 1, 2, or 3\n    seatHeaterRearRight, // 0 = off, else 1, 2, or 3\n    seatHeaterRight, // 0 = off, else 1, 2, or 3\n    sideMirrorHeaters, // boolean\n    timestamp, // unix epoch timestamp again\n    wiperBladeHeater: false\n  }\n} = await vehicles.climateState({ id, token })\n```\n\n- On `timdorr`: [`get-api-1-vehicles-id-data_request-climate_state`](https://tesla-api.timdorr.com/vehicle/state/climatestate#get-api-1-vehicles-id-data_request-climate_state)\n- On `teslaapi`: ['climate-state'](https://www.teslaapi.io/vehicles/state-and-settings#climate-state)\n\n---\n\n#### `driveState`\n\nThe car's current location and driving state. (This is the same as the `driveState` field in the response to `vehicles.vehicleData()`)\n\n```js\nconst {\n  response: {\n    gpsAsOf, // unix epoch timestamp\n    heading, // e.g. 340 0 to 360 integer degrees\n    latitude, // e.g. -30.336537\n    longitude, // e.g. 141.145116,\n    nativeLatitude, // e.g. -30.336537  TODO: what's this all about?\n    nativeLocationSupported, // e.g. 1  TODO: what's this all about?\n    nativeLongitude, // e.g. 141.145116  TODO: what's this all about?\n    nativeType, // e.g. \"wgs\"  TODO: get acceptable values for this\n    power, // e.g. 0  TODO: get acceptable values for this\n    shiftState, // e.g. null  TODO: get acceptable values for this\n    speed, // e.g. null  TODO: find out the units for this but my guess is imperial units (mph)\n    timestamp // e.g. 1600552117638\n  }\n} = await vehicles.driveState({ id, token })\n```\n\n- On `timdorr`: [`get-api-1-vehicles-id-data_request-drive_state`](https://tesla-api.timdorr.com/vehicle/state/drivestate#get-api-1-vehicles-id-data_request-drive_state)\n- On `teslaapi`: ['drive-state'](https://www.teslaapi.io/vehicles/state-and-settings#drive-state)\n\n---\n\n#### `guiSettings`\n\nLocalisation settings including units for distances, temperatures, and charge, as well as the clock type. (This is the same as the `guiSettings` field in the response to `vehicles.vehicleData()`)\n\n```js\nconst {\n  response: {\n    gui24HourTime, // boolean\n    guiChargeRateUnits, // e.g. \"kW\"  TODO: get acceptable values for this\n    guiDistanceUnits, // e.g. \"km/hr\"  TODO: get acceptable values for this\n    guiRangeDisplay, // e.g. \"Rated\"  TODO: get acceptable values for this\n    guiTemperatureUnits, // e.g. \"C\"  TODO: get acceptable values for this\n    showRangeUnits, // boolean\n    timestamp: gsTimestamp // unix epoch timestamp\n  }\n} = await vehicles.guiSettings({ id, token })\n```\n\n- On `timdorr`: [`get-api-1-vehicles-id-data_request-gui_settings`](https://tesla-api.timdorr.com/vehicle/state/guisettings#get-api-1-vehicles-id-data_request-gui_settings)\n- On `teslaapi`: ['gui-settings'](https://www.teslaapi.io/vehicles/state-and-settings#gui-settings)\n\n---\n\n#### `mobileEnabled`\n\nIs mobile access enabled?\n\n```js\nconst { response: mobileEnabled } = await vehicles.mobileEnabled({ id, token })\n```\n\n- On `timdorr`: [`get-api-1-vehicles-id-mobile_enabled`](https://tesla-api.timdorr.com/vehicle/state/mobileenabled#get-api-1-vehicles-id-mobile_enabled)\n- On `teslaapi`: ['mobile-enabled'](https://www.teslaapi.io/vehicles/state-and-settings#mobile-enabled)\n\n---\n\n#### `serviceData`\n\nCurrent servicing data.\n\n```js\nconst {\n  response: {\n    // unknown fields - maybe only of use when the car is booked in for service.\n    ...serviceData\n  }\n} = await vehicles.serviceData({ id, token })\n```\n\n- On `timdorr`: not mentioned\n- On `teslaapi`: ['vehicle-service-data'](https://www.teslaapi.io/vehicles/state-and-settings#vehicle-service-data)\n\n---\n\n#### `nearbyChargingSites`\n\nLists Tesla-operated charging stations near to the car.\n\n```js\nconst {\n  response: {\n    congestionSyncTimeUtcSecs, // integer number of seconds\n    destinationCharging: [\n      {\n        location: {\n          lat: dcLat, //  e.g. -35.312247\n          long: dcLong, // e.g. 149.133236\n        },\n        name: dcName, // e.g. \"Hotel Realm Canberra\"\n        type: dcType, // e.g. \"destination\"\n        distanceMiles: dcDist // e.g. 11.807002\n      }\n    ],\n    superchargers: [\n      {\n        location: {\n          lat: scLat, // e.g. -35.294304,\n          long: scLong, // e.g. 149.190322\n        },\n        name: scName, // e.g. \"Canberra, ACT\"\n        type: scType, // e.g. \"supercharger\"\n        distanceMiles: scDist, // e.g. 11.87435\n        availableStalls, // e.g. 5\n        totalStalls, // e.g. 6\n        siteClosed // boolean\n      }\n    ],\n    \"timestamp\" // unix epoch timestamp\n  }\n} = await vehicles.nearbyChargingSites({ id, token })\n```\n\n- On `timdorr`: [`get-api-1-vehicles-id-nearby_charging_sites`](https://tesla-api.timdorr.com/vehicle/state/nearbychargingsites#get-api-1-vehicles-id-nearby_charging_sites)\n- On `teslaapi`: not mentioned\n\n---\n\n#### `upcomingCalendarEntries`\n\nIf you have allowed your car to share your calendar then this will list your upcoming calendar entries.\n\n```js\nconst {\n  response: { result, reason }\n} = await vehicles.upcomingCalendarEntries({ id, token })\n```\n\n- On `timdorr`: [`calendar`](https://tesla-api.timdorr.com/vehicle/commands/calendar)\n- On `teslaapi`: [`upcoming-calendar-entries`](https://www.teslaapi.io/vehicles/commands#upcoming-calendar-entries)\n\n---\n\n### Commands\n\nIt's great to be able to get data from your car, but what about making it do things? We already saw the `wake` command above.\n\nCommands all return a response with a `result` (boolean) and, if the `result` is `false`, a `reason` string.\n\n---\n\n#### `honkHorn`\n\nBeeps the car's horn. _toot!_\n\n```js\nconst {\n  response: { result, reason }\n} = await vehicles.honkHorn({ id, token })\n```\n\n- On `timdorr`: [`post-api-1-vehicles-id-command-honk_horn`](https://tesla-api.timdorr.com/vehicle/commands/alerts#post-api-1-vehicles-id-command-honk_horn)\n- On `teslaapi`: [`honk-horn`](https://www.teslaapi.io/vehicles/commands#honk-horn)\n\n---\n\n#### `flashLights`\n\nFlashes the car's headlights.\n\n```js\nconst {\n  response: { result, reason }\n} = await vehicles.flashLights({ id, token })\n```\n\n- On `timdorr`: [`post-api-1-vehicles-id-command-flash_lights`](https://tesla-api.timdorr.com/vehicle/commands/alerts#post-api-1-vehicles-id-command-flash_lights)\n- On `teslaapi`: [`flash-lights`](https://www.teslaapi.io/vehicles/commands#flash-lights)\n\n---\n\n#### `autoConditioningStart`\n\nStart the car's climate control system. It will use the temperature and set-warming options you've previously set. Repeated calls to this will not cause an error, though obviously if the car's climate control system is on it's not going to turn on again.\n\n```js\nconst {\n  response: { result, reason }\n} = await vehicles.autoConditioningStart({ id, token })\n```\n\n- On `timdorr`: [`post-api-1-vehicles-id-command-auto_conditioning_start`](https://tesla-api.timdorr.com/vehicle/commands/climate#post-api-1-vehicles-id-command-auto_conditioning_start)\n- On `teslaapi`: [`start-hvac-system`](https://www.teslaapi.io/vehicles/commands#start-hvac-system)\n\n---\n\n#### `autoConditioningStop`\n\nStop the car's climate control system.\n\n**Note**: If you call this when the car's climate control system is already off you will get a `ECONNABORTED` error rather than a response of `{ result: false, reason: 'some reason' }`.\n\n```js\nconst {\n  response: { result, reason }\n} = await vehicles.autoConditioningStop({ id, token })\n```\n\n- On `timdorr`: [`post-api-1-vehicles-id-command-auto_conditioning_stop`](https://tesla-api.timdorr.com/vehicle/commands/climate#post-api-1-vehicles-id-command-auto_conditioning_stop)\n- On `teslaapi`: [`stop-hvac-system`](https://www.teslaapi.io/vehicles/commands#stop-hvac-system)\n\n---\n\n#### `setTemps`\n\nSets the temperature for the car's climate control system.\n\nThe request requires the parameter `driverTemp`. It also accepts a `passengerTemp` but only the `driverTemp` is actually used right now. This may change in the future.\n\n##### Notes\n\n- The values for `driverTemp` and `passengerTemp` are always in Metric (`°C`) no matter what you have set in `guiSettings`.\n- If you set the temperature very low or very high the HVAC system will start heating or cooling immediately.\n\n```js\nconst driverTemp = 23.4 // degrees celsius.\nconst {\n  response: { result, reason }\n} = await vehicles.setTemps({ id, token, driverTemp })\n```\n\n- On `timdorr`: [`post-api-1-vehicles-id-command-auto_conditioning_stop`](https://tesla-api.timdorr.com/vehicle/commands/climate#post-api-1-vehicles-id-command-auto_conditioning_stop)\n- On `teslaapi`: [`stop-hvac-system`](https://www.teslaapi.io/vehicles/commands#stop-hvac-system) the api claims that the params get passed in as query params but this is not actually true.\n\n---\n\n#### `setPreconditoningMax`\n\nToggles the climate controls between Max Defrost and the previous setting.\n\nYou can pass `on: true`, or 'on: false' to this multiple times, without error.\n\n```js\nconst {\n  response: { result, reason }\n} = await vehicles.setPreconditioningMax({ id, token, on: true })\n```\n\n- On `timdorr`: [`post-api-1-vehicles-id-command-set_preconditioning_max`](https://tesla-api.timdorr.com/vehicle/commands/climate#post-api-1-vehicles-id-command-set_preconditioning_max)\n- On `teslaapi`: not listed\n\n---\n\n#### `setSeatHeater`\n\nSets the seat heater level for the nominated seat.\n\n**Note** You _must_ have already turned the car's climate system on first with `autoConditioningStart` for this to work. If you don't you'll get an error. Also in testing I found this API call quite prone to timeout errors.\n\n| Value | Seat        |\n| ----- | ----------- |\n| `0`   | front left  |\n| `1`   | front right |\n| `2`   | rear left   |\n| `3`   | rear center |\n| `4`   | rear right  |\n\n```js\nconst {\n  response: { result, reason }\n} = await vehicles.setSeatHeater({ id, token, heater: 0, level: 1 })\n```\n\n- On `timdorr`: [`post-api-1-vehicles-id-command-remote_seat_heater_request`](https://tesla-api.timdorr.com/vehicle/commands/climate#post-api-1-vehicles-id-command-remote_seat_heater_request)\n- On `teslaapi`: not listed\n\n---\n\n#### `setSteeringWheelHeater`\n\nTurns the steering wheel heater on or off.\n\n**Note** You _must_ have already turned the car's climate system on first with `autoConditioningStart` for this to work. If you don't you'll get an error.\n\n**Also Note** I am not sure that my Model 3 even has a steering wheel heater so all I get from this is a timeout error.\n\n```js\nconst {\n  response: { result, reason }\n} = await vehicles.setSteeringWheelHeater({ id, token, on: true }) // or on: false\n```\n\n- On `timdorr`: [`post-api-1-vehicles-id-command-remote_steering_wheel_heater_request`](https://tesla-api.timdorr.com/vehicle/commands/climate#post-api-1-vehicles-id-command-remote_steering_wheel_heater_request)\n- On `teslaapi`: not listed\n\n---\n\n#### `mediaTogglePlayback`\n\nEither toggles the media between `playing` and `paused`, or if the car is tuned to a radio station, this mutes or un-mutes the audio.\n\n**Note** You, or someone, _must_ have turned the car on and be sitting in it for this to work. If you don't you'll get a 'user_not_present' error.\n\n```js\nconst {\n  response: { result, reason }\n} = await vehicles.mediaTogglePlayback({ id, token })\n```\n\n- On `timdorr`: [`post-api-1-vehicles-id-command-media_toggle_playback`](https://tesla-api.timdorr.com/vehicle/commands/media#post-api-1-vehicles-id-command-media_toggle_playback)\n- On `teslaapi`: not listed\n\n---\n\n#### `mediaNextTrack`\n\nSkips the media to the next track, unless the car is tuned to a radio station.\n\n**Note** You, or someone, _must_ have turned the car on and be sitting in it for this to work. If you don't you'll get a 'user_not_present' error.\n\n```js\nconst {\n  response: { result, reason }\n} = await vehicles.mediaNextTrack({ id, token })\n```\n\n- On `timdorr`: [`post-api-1-vehicles-id-command-media_next_track`](https://tesla-api.timdorr.com/vehicle/commands/media#post-api-1-vehicles-id-command-media_next_track)\n- On `teslaapi`: not listed\n\n---\n\n#### `mediaPrevTrack`\n\nSkips the media to the previous track, unless the car is tuned to a radio station.\n\n**Note** You, or someone, _must_ have turned the car on and be sitting in it for this to work. If you don't you'll get a 'user_not_present' error.\n\n```js\nconst {\n  response: { result, reason }\n} = await vehicles.mediaPrevTrack({ id, token })\n```\n\n- On `timdorr`: [`post-api-1-vehicles-id-command-media_prev_track`](https://tesla-api.timdorr.com/vehicle/commands/media#post-api-1-vehicles-id-command-media_prev_track)\n- On `teslaapi`: not listed\n\n---\n\n#### `mediaNextFav`\n\nSkips the media to the next 'favourite', however that is defined, **e.g** if the car is tuned to a radio station, it switches to the next radio station in your favourites.\n\n**Note** You, or someone, _must_ have turned the car on and be sitting in it for this to work. If you don't you'll get a 'user_not_present' error.\n\n```js\nconst {\n  response: { result, reason }\n} = await vehicles.mediaNextFav({ id, token })\n```\n\n- On `timdorr`: [`post-api-1-vehicles-id-command-media_next_track`](https://tesla-api.timdorr.com/vehicle/commands/media#post-api-1-vehicles-id-command-media_next_track)\n- On `teslaapi`: not listed\n\n---\n\n#### `mediaPrevFav`\n\nSkips the media to the previous 'favourite', however that is defined, **e.g** if the car is tuned to a radio station, it switches to the previous radio station in your favourites.\n\n**Note** You, or someone, _must_ have turned the car on and be sitting in it for this to work. If you don't you'll get a 'user_not_present' error.\n\n```js\nconst {\n  response: { result, reason }\n} = await vehicles.mediaPrevFav({ id, token })\n```\n\n- On `timdorr`: [`post-api-1-vehicles-id-command-media_prev_track`](https://tesla-api.timdorr.com/vehicle/commands/media#post-api-1-vehicles-id-command-media_prev_track)\n- On `teslaapi`: not listed\n\n---\n\n#### `mediaVolumeUp`\n\nTurns the volume up.\n\n**Note** You, or someone, _must_ have turned the car on and be sitting in it for this to work. If you don't you'll get a 'user_not_present' error.\n\n```js\nconst {\n  response: { result, reason }\n} = await vehicles.mediaVolumeUp({ id, token })\n```\n\n- On `timdorr`: [`post-api-1-vehicles-id-command-media_volume_up`](https://tesla-api.timdorr.com/vehicle/commands/media#post-api-1-vehicles-id-command-media_volume_up)\n- On `teslaapi`: not listed\n\n---\n\n#### `mediaVolumeDown`\n\nTurns the volume down.\n\n**Note** You, or someone, _must_ have turned the car on and be sitting in it for this to work. If you don't you'll get a 'user_not_present' error.\n\n```js\nconst {\n  response: { result, reason }\n} = await vehicles.mediaVolumeDown({ id, token })\n```\n\n- On `timdorr`: [`post-api-1-vehicles-id-command-media_volume_down`](https://tesla-api.timdorr.com/vehicle/commands/media#post-api-1-vehicles-id-command-media_volume_down)\n- On `teslaapi`: not listed\n\n---\n\n#### `share`\n\nShare a video url, or navigation destination. If the car is in 'theatre mode' the url will launch the appropriate player. If the `value` you send is a street address, then it will set the navigation system to navigate to that address.\n\nIf the car can't understand the value you send it will return an error.\n\n```js\nconst value = '1 Commonwealth Avenue, Yarralumla ACT 2600, Australia'\n\nconst {\n  response: { result, reason }\n} = await vehicles.share({ id, token, value, locale: 'en-AU' }) // locale is optional, it will default to your OS's system locale.\n```\n\n- On `timdorr`: [`post-api-1-vehicles-id-command-share`](https://tesla-api.timdorr.com/vehicle/commands/sharing#post-api-1-vehicles-id-command-share)\n- On `teslaapi`: not listed\n\n---\n\n#### `setSentryMode`\n\nTurn sentry mode on or off.\n\n```js\nconst {\n  response: { result, reason }\n} = await vehicles.setSentryMode({ id, token, on: true }) // or `on: false` for off.\n```\n\n- On `timdorr`: [`post-api-1-vehicles-id-command-set_sentry_mode`](https://tesla-api.timdorr.com/vehicle/commands/sentrymode#post-api-1-vehicles-id-command-set_sentry_mode)\n- On `teslaapi`: not listed\n\n---\n\n#### `actuateTrunk`\n\nOpens (or 'pops' depending on your hardware) the 'frunk' or boot.\n\n```js\nconst {\n  response: { result, reason }\n} = await vehicles.actuateTrunk({ id, token, which: 'front' }) // for the 'frunk', or `which: 'rear'` for the boot.\n```\n\n- On `timdorr`: [`post-api-1-vehicles-id-command-actuate_trunk`](https://tesla-api.timdorr.com/vehicle/commands/trunk#post-api-1-vehicles-id-command-actuate_trunk)\n- On `teslaapi`: not listed\n\n---\n\n#### `windowControl`\n\nLets you 'vent' or 'close' the car's windows.\n\n**Note** to 'close' the windows you must also provide a gps location that's close to the car. You can get the car's current gps location from `vehicles.driveState`. Alternatively you could issue a `lock` command which will also close the windows if the car was not locked.\n\n```js\nconst {\n  response: { result, reason }\n} = await vehicles.windowControl({ id, token, command: 'vent' })\n```\n\nor\n\n```js\nconst {\n  response: { result, reason }\n} = await vehicles.windowControl({ id, token, command: 'close', lat: -35.297476, lon: 149.12579 })\n```\n\n- On `timdorr`: [`post-api-1-vehicles-id-command-window_control`](https://tesla-api.timdorr.com/vehicle/commands/windows#post-api-1-vehicles-id-command-window_control)\n- On `teslaapi`: not listed\n\n---\n\n#### `sunRoofControl`\n\nLets you 'vent' or 'close' the car's sun roof if it has a sun roof.\n\n```js\nconst {\n  response: { result, reason }\n} = await vehicles.sunRoofControl({ id, token, state: 'vent' })\n```\n\n- On `timdorr`: [`post-api-1-vehicles-id-command-sun_roof_control`](https://tesla-api.timdorr.com/vehicle/commands/sunroof#post-api-1-vehicles-id-command-sun_roof_control)\n- On `teslaapi`: not listed\n\n---\n\n#### `triggerHomelink`\n\nLets you trigger the HomeLink controller if it is connected.\n\n**Note** You must also provide a gps location that's close to the homelink device.\n\n```js\nconst {\n  response: { result, reason }\n} = await vehicles.triggerHomelink({ id, token, lat: -35.297476, lon: 149.12579 })\n```\n\n- On `timdorr`: [`post-api-1-vehicles-id-command-trigger_homelink`](https://tesla-api.timdorr.com/vehicle/commands/homelink#post-api-1-vehicles-id-command-trigger_homelink)\n- On `teslaapi`: not listed\n\n---\n\n#### `scheduleSoftwareUpdate`\n\nIf you have a pending software update, this command lets you schedule a time for the install to happen. If you do not provide an offset then it will attempt to install immediately.\n\nIf there is no software update available you'll get a `result: false` and `reason: update_not_available`.\n\n```js\nconst {\n  response: { result, reason }\n} = await vehicles.scheduleSoftwareUpdate({ id, token })\n```\n\nor, to install in an hour:\n\n```js\nconst {\n  response: { result, reason }\n} = await vehicles.scheduleSoftwareUpdate({ id, token, offset: 3600 }) // offset is in seconds\n```\n\n- On `timdorr`: [`post-api-1-vehicles-id-command-schedule_software_update`](https://tesla-api.timdorr.com/vehicle/commands/softwareupdate#post-api-1-vehicles-id-command-schedule_software_update)\n- On `teslaapi`: not listed\n\n---\n\n#### `cancelSoftwareUpdate`\n\nIf you have a pending software update, and you've scheduled an installation time, then this lets you cancel that installation.\n\nIf there is no software update scheduled you'll get a `result: false` and `reason: no_update_scheduled`.\n\n```js\nconst {\n  response: { result, reason }\n} = await vehicles.cancelSoftwareUpdate({ id, token })\n```\n\n- On `timdorr`: [`post-api-1-vehicles-id-command-cancel_software_update`](https://tesla-api.timdorr.com/vehicle/commands/softwareupdate#post-api-1-vehicles-id-command-cancel_software_update)\n- On `teslaapi`: not listed\n\n---\n\n#### `setValetMode`\n\nValet Mode limits the car's top speed to 110 Kilometres per hour and 80kW of acceleration power. It also disables Homelink, Bluetooth, and Wifi settings, as well as the ability to disable mobile access to the car.\n\nIt also hides your favourites, as well as your home, and work locations in navigation.\n\nIf you provide a password then anyone with that password, (a numeric PIN) can disable Valet Mode from the screen in the car. You can always disable Valet Mode from the API without a password however. It only applies to the person driving your car.\n\n```js\nconst {\n  response: { result, reason }\n} = await vehicles.setValetMode({ id, token, on: true, password: 1234 })\n```\n\n- On `timdorr`: [`post-api-1-vehicles-id-command-set_valet_mode`](https://tesla-api.timdorr.com/vehicle/commands/valet#post-api-1-vehicles-id-command-set_valet_mode)\n- On `teslaapi`: [`set-valet-mode`](https://www.teslaapi.io/vehicles/commands#set-valet-mode)\n\n---\n\n#### `resetValetPin`\n\nClears the Valet Mode `PIN`, meaning that once Valet Mode is disabled, you can enable it with or without a new `PIN`.\n\n```js\nconst {\n  response: { result, reason }\n} = await vehicles.resetValetPin({ id, token })\n```\n\n- On `timdorr`: [`post-api-1-vehicles-id-command-reset_valet_pin`](https://tesla-api.timdorr.com/vehicle/commands/valet#post-api-1-vehicles-id-command-reset_valet_pin)\n- On `teslaapi`: [`reset-valet-pin`](https://www.teslaapi.io/vehicles/commands#reset-valet-pin)\n\n---\n\n## `logs`\n\nUsing the `accessToken` issued above, if you have the appropriate 'entitlements' (defined by Tesla and embedded into the token Tesla give you) you can you use the `logs` functions to perform diagnostics on your account. Use `logs.getEntitlements` to check if you have the right permissions.\n\n```js\nconst { logs } = require('node-tesla-api')\n```\n\n---\n\n### `getEntitlements`\n\nDoes your `token` allow you to perform diagnostics?\n\n```js\nconst {\n  response: { eligible } // eligible will be true or false\n} = await logs.getEntitlements({ token })\n```\n\n- On `timdorr`: not listed\n- On `teslaapi`: [`logs/diagnostics#entitlements`](https://www.teslaapi.io/logs/diagnostics#entitlements)\n\n---\n\n### `getLogs`\n\nIf you are eligible for logs you can get the account logs associated with your token. _hint_ you probably are not eligible.\n\n```js\nconst {\n  response: { result, reason }\n} = await logs.getLogs({ token })\n```\n\n- On `timdorr`: not listed\n- On `teslaapi`: [`logs/logs`](https://www.teslaapi.io/logs/logs)\n\n---\n\n### `sendEntitlements`\n\nIt's hard to know what this does.\n\n```js\nconst {\n  response: { result, reason }\n} = await logs.sendEntitlements({ token })\n```\n\n- On `timdorr`: not listed\n- On `teslaapi`: [`logs/diagnostics#send`](https://www.teslaapi.io/logs/diagnostics#send)\n\n---\n\n## Development\n\n\u003c!-- prettier-ignore --\u003e\n| branch | status | coverage | audit | notes |\n| ------ | ------ | -------- | ----- | ----- |\n| `develop` | [![CircleCI](https://circleci.com/gh/davesag/node-tesla-api/tree/develop.svg?style=svg)](https://circleci.com/gh/davesag/node-tesla-api/tree/develop) | [![codecov](https://codecov.io/gh/davesag/node-tesla-api/branch/develop/graph/badge.svg)](https://codecov.io/gh/davesag/node-tesla-api) | [![Vulnerabilities](https://snyk.io/test/github/davesag/node-tesla-api/develop/badge.svg)](https://snyk.io/test/github/davesag/node-tesla-api/develop) | work in progress |\n| `main`  | [![CircleCI](https://circleci.com/gh/davesag/node-tesla-api/tree/main.svg?style=svg)](https://circleci.com/gh/davesag/node-tesla-api/tree/main) | [![codecov](https://codecov.io/gh/davesag/node-tesla-api/branch/main/graph/badge.svg)](https://codecov.io/gh/davesag/node-tesla-api) | [![Vulnerabilities](https://snyk.io/test/github/davesag/node-tesla-api/main/badge.svg)](https://snyk.io/test/github/davesag/node-tesla-api/main) | latest stable release |\n\n### Prerequisites\n\n- [NodeJS](https://nodejs.org). I use [`nvm`](https://github.com/creationix/nvm) to manage Node versions — `brew install nvm`.\n\n### Install dependencies\n\n```sh\nnpm install\n```\n\n### Linting\n\n```sh\nnpm run lint\n```\n\nNote this will also run whenever you commit file changes.\n\n### Formatting via Prettier\n\n```sh\nnpm run prettier\n```\n\n**Note**: this will also run whenever you commit file changes.\n\n### Testing\n\n```sh\nnpm test\n```\n\nor with code coverage\n\n```sh\nnpm run test:unit:cov\n```\n\n## Contributing\n\nPlease see the [contributing notes](CONTRIBUTING.md).\n\n## To Do\n\n- Cross check the API with the latest updates\n- Add API unit tests and bring test coverage to 100%\n- DRY up the code some more\n- Improve documentation\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavesag%2Fnode-tesla-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdavesag%2Fnode-tesla-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavesag%2Fnode-tesla-api/lists"}