Have ideas to improve npm?Join in the discussion! ¬Ľ

    node-tesla-api

    0.1.0¬†‚Äʬ†Public¬†‚Äʬ†Published

    node-tesla-api

    A modern NodeJS implementation of the (unofficial) Tesla API.

    NPM

    Under development: features outlined below may not be final.

    Usage

    npm i node-tesla-api

    I'm only focussing on the oauth, vehicles, and logs parts of the Tesla API for now.

    The API follows the commands outlined in the (unofficial) Tesla API, but uses camelCase instead of underscores.

    You'll need to have access to a Tesla, and have a valid Tesla username and password to make use of this API.

    Please feel free to use my Tesla referral code if you buy a Tesla - we both get some free charging that way.

    My code is: david60377

    Example

    const { oauth, vehicles } = require('node-tesla-api')
     
    const sleep = async delay => new Promise(resolve => setTimeout(resolve, delay))
     
    const wakeCar = async ({ id, token, retry = 0, maxRetries = 3 }) => {
      if (retry === maxRetries) return
     
      const {
        response: { state } 
      } = await vehicles.vehicle({ id, token })
      if (state === 'online') return
     
      await vehicles.wake({ id, token })
      await sleep(DELAY)
      // try again
      await wakeCar({ id, token, retry: retry + 1, maxRetries })
    }
     
    const start = async (email, password) => {
      const { accessToken: token } = await oauth.token({
        email,
        password,
        // These values are an open secret.
        // See https://tesla-api.timdorr.com for the latest values.
        clientSecret: 'get-me-from-pastebin',
        clientId: 'also-get-me-from-pastebin'
      })
      console.log('token', token)
     
      const { response: cars } = await vehicles.list({ token })
      console.log('cars', cars)
     
      const { idS: id } = cars.find(car => car.displayName === 'Terry')
      await wakeCar({ id, token })
     
      const { response: state } = await vehicles.vehicleState({ id, token })
      console.log('state', JSON.stringify(state, null, 2))
    }
     
    start('your-tesla@account.email', 'Y0uRP@55w0rd').catch(err => {
      console.error(err)
    })

    API

    The API is broken down into

    • oauth ‚ÄĒ¬†you provide your username and password and get back a token.
    • vehicles - using the token you interact with your vehicles
    • logs - using the token you can perform various diagnostics, but only if the token has the correct embedded permissions.

    oauth

    Controls how you obtain, refresh and revoke tokens.

    const { oauth } = require('node-tesla-api')

    token

    Returns the accessToken you will need to invoke the other api functions.

    const { accessToken, refreshToken, tokenType, createdAt, expiresIn } = await oauth.token({
      email: 'your-tesla@account.email',
      password: 'your-password',
      clientSecret: 'get-me-from-pastebin',
      clientId: 'also-get-me-from-pastebin'
    })

    refresh

    Returns a refreshed accessToken. Use this if your original token has expired.

    const { accessToken, refreshToken, tokenType, createdAt, expiresIn } = await oauth.refresh({
      refreshToken: 'the refresh token you got back from the `token` function',
      clientSecret: 'get-me-from-pastebin',
      clientId: 'also-get-me-from-pastebin'
    })

    revoke

    Revokes an accessToken. Use this to log the user out.

    await oauth.revoke({ token: 'the access token you got back from the `token` function' })

    vehicles

    Using the accessToken issued above you use the vehicles functions to interact with your car.

    const { vehicles } = require('node-tesla-api')

    list

    Get a list of your vehicles.

    const { response: cars } = await vehicles.list({ token })
     
    const {
      id, // don't use this integer version as the number overflows 
      vehicleId, // a number, unsure what it's used for
      vin, // a string
      displayName, // a string
      optionCodes, // a string of comma separated codes
      color, // not sure - usually null
      accessType, // e.g. 'OWNER'
      tokens, // an array of tokens
      state, // "online" if the car is online
      inService, // boolean
      idS, // use this string version of the id instead of id
      calendarEnabled, // boolean
      apiVersion, // a number, e.g. 10 right now.
      backseatToken, // unsure what this is
      backseatTokenUpdatedAt // timestamp or null
      vehicleConfig, // e.g. null
    } = cars[0]

    vehicle

    Get the basic details of a specific vehicle.

    // using the `idS` field returned from `vehicles.list`, not the `id`, or `vehicleId`.
    // and the token from `oauth.token`
    const {
      id, // don't use this integer version as the number overflows 
      vehicleId, // a number, unsure what it's used for
      vin, // a string
      displayName, // a string
      optionCodes, // a string of comma separated codes
      color, // not sure - usually null
      accessType, // e.g. 'OWNER'
      tokens, // an array of two tokens
      state, // "online" if the car is online
      inService, // boolean
      idS, // use this string version of the id instead of id
      calendarEnabled, // boolean
      apiVersion, // a number, e.g. 10 right now.
      backseatToken, // unsure what this is
      backseatTokenUpdatedAt // timestamp or null
      vehicleConfig, // e.g. null
    } = await vehicles.vehicle({ id, token })

    The keen observer will note that this is the same data as returned in the vehicle list response.


    wake

    When you first get the details of your car, you need to check the state to see if it's 'online' or not.

    If the car's state is 'asleep' or otherwise not 'online' then you need to wake it up before you can do anything with it.

    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.

    To wake up the car you send it a wake command as follows:

    await vehicles.wake({ id, token })

    Now 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.

    You need to keep checking the state and reissuing the wake command until either the car really wakes up, or decide to stop trying.

    // Check the `state` of the car recursively, trying three times to wake it up.
    const wakeCar = async ({ id, token, retry = 0, maxRetries = 3 }) => {
      if (retry === maxRetries) return
     
      const {
        response: { state } 
      } = await vehicles.vehicle({ id, token })
      if (state === 'online') return
     
      await vehicles.wake({ id, token })
      await sleep(DELAY)
      // try again
      await wakeCar({ id, token, retry: retry + 1, maxRetries })
    }

    Then you can just call

    await wakeCar({ id, token })

    ToDo: Compose a high-level API that simplifies the use of this low-level API wrapper. (See issues/28)


    vehicleData

    Now you know how to wake your car, let's take a look at the full set of car data.

    const {
      response: {
        id, // don't use this. 
        userId,
        vehicleId, // or this
        vin,
        displayName, // TODO: Is this ever different to `vehicleName`?
        optionCodes,
        color,
        accessType, // e.g. "OWNER"  TODO: find out these values.
        tokens, // array of two small strings
        state, // should be "online",
        inService, // boolean,
        idS, // use this instead of `id`
        calendarEnabled, // boolean
        apiVersion, // e.g. 10
        backseatToken, // TODO: find out what this is for
        backseatTokenUpdatedAt, // TODO: find out what this is for
        vehicleConfig: {
          canAcceptNavigationRequests, // boolean
          canActuateTrunks, // boolean
          carSpecialType, // e.g. "base" TODO: find out these values.
          carType, // mine is a "model3"  TODO: find out these values.
          chargePortType, // mine is "CCS"  TODO: find out these values.
          eceRestrictions, // boolean
          euVehicle, // boolean (e.g. true but I am in AU)
          exteriorColor, // mine is "MidnightSilver"  TODO: find out these values.
          hasAirSuspension, // boolean
          hasLudicrousMode, // boolean
          keyVersion, // e.g. 2
          motorizedChargePort, // boolean
          plg, // boolean (e.g. false)
          rearSeatHeaters, // e.g. 1 - I have rear seat heaters
          rearSeatType, // e.g. null
          rhd, // right hand drive? (e.g. true)
          roofColor, // e.g. "Glass"  TODO: find out these values.
          seatType, // e.g. null
          spoilerType, // e.g. "None"
          sunRoofInstalled, // e.g. null,
          thirdRowSeats, // e.g. "<invalid>",  TODO: find out these values.
          timestamp: vcTimestamp, // unix epoch timestamp
          useRangeBadging, // e.g. true,
          wheelType, // e.g. "Pinwheel18"  TODO: find out these values.
        },
        chargeState: {
          batteryHeaterOn, // boolean
          batteryLevel, // integer percentage
          batteryRange, // floating point value using imperial units (miles)
          chargeCurrentRequest, // how many amps the car wants (e.g. 8)
          chargeCurrentRequestMax,  // how many amps the car can have (e.g. 8)
          chargeEnableRequest, // boolean
          chargeEnergyAdded, // floating point number (e.g 10.15)
          chargeLimitSoc, // integer percentage (e.g 94)
          chargeLimitSocMax,  // integer percentage (e.g 100)
          chargeLimitSocMin,   // integer percentage (e.g 50)
          chargeLimitSocStd,  // integer percentage (e.g 90)
          chargeMilesAddedIdeal,   // floating point number (e.g 41.5)
          chargeMilesAddedRated,   // floating point number (e.g 41.5)
          chargePortColdWeatherMode, // boolean
          chargePortDoorOpen, // boolean
          chargePortLatch, // e.g "Engaged"  TODO: find out these values.
          chargeRate, // a number TODO: check these values when charging the car
          chargeToMaxRange, // boolean
          chargerActualCurrent, // a number e.g 0   TODO: check these values when charging the car
          chargerPhases, // 1 = single, 3 = three  TODO: is there such a thing as 2 phase power?
          chargerPilotCurrent, // something else measured in amps (e.g. 8)
          chargerPower, // a number (TODO: check these values when charging the car)
          chargerVoltage, // an integer (e.g 2)
          chargingState, // e.g. "Stopped"  TODO: find out these values.
          connChargeCable, // e.g. "IEC"  TODO: find out these values.
          estBatteryRange, // floating point value using imperial units (miles) (e.g. 273.36)
          fastChargerBrand, // e.g. "<invalid>"
          fastChargerPresent, // boolean
          fastChargerType, // e.g. "MCSingleWireCAN"  TODO: find out these values.
          idealBatteryRange,// floating point value using imperial units (miles) (e.g. 281.16)
          managedChargingActive, // boolean
          managedChargingStartTime, // a timestamp or null
          managedChargingUserCanceled, // boolean
          maxRangeChargeCounter, // TODO: maybe how the car knows to warn you about overcharging.
          minutesToFullCharge, // integer count (e.g 0)
          notEnoughPowerToHeat: null, // e.g. null  TODO: find out these values.
          scheduledChargingPending, // boolean
          scheduledChargingStartTime, //  unix epoch timestamp
          timeToFullCharge, // integer count (e.g 0)
          timestamp: chsTimestamp,//  unix epoch timestamp
          tripCharging, // boolean
          usableBatteryLevel, // integer percentage (e.g 93)
          userChargeEnableRequest // e.g. null  TODO: find out these values.
        },
        climateState: {
          batteryHeater, // boolean
          batteryHeaterNoPower, // e.g. null  TODO: find out these values.
          climateKeeperMode, // e.g "off"  TODO: find out these values.
          defrostMode, // e.g. 0.  TODO: find out these values.
          driverTempSetting, // e.g. 22 (uses GUI setting `guiTemperatureUnits`)
          fanStatus, // e.g. 0.  TODO: find out these values.
          insideTemp, // e.g. 16.2 (uses GUI setting `guiTemperatureUnits`)
          isAutoConditioningOn, // boolean
          isClimateOn, // boolean
          isFrontDefrosterOn, // boolean
          isPreconditioning, // boolean
          isRearDefrosterOn, // boolean
          leftTempDirection, // e.g. 326 - range is 0 to 360 presumably.
          maxAvailTemp, // e.g. 28 (uses GUI setting `guiTemperatureUnits`)
          minAvailTemp, // e.g. 15 (uses GUI setting `guiTemperatureUnits`)
          outsideTemp, // e.g. 15.5 (uses GUI setting `guiTemperatureUnits`)
          passengerTempSetting, // e.g. 22 (uses GUI setting `guiTemperatureUnits`)
          remoteHeaterControlEnabled, // boolean
          rightTempDirection // e.g. 326 - range is 0 to 360 presumably.
          seatHeaterLeft, // 0 = off, else 1, 2, or 3
          seatHeaterRearCenter, // 0 = off, else 1, 2, or 3
          seatHeaterRearLeft, // 0 = off, else 1, 2, or 3
          seatHeaterRearRight, // 0 = off, else 1, 2, or 3
          seatHeaterRight, // 0 = off, else 1, 2, or 3
          sideMirrorHeaters, // boolean
          timestamp: clsTimestamp, // unix epoch timestamp again
          wiperBladeHeater: false
        },
        driveState: {
          gpsAsOf, // unix epoch timestamp
          heading, // e.g. 340 0 to 360 integer degrees
          latitude, // e.g. -30.336537
          longitude, // e.g. 141.145116,
          nativeLatitude, // e.g. -30.336537  TODO: what's this all about?
          nativeLocationSupported, // e.g. 1  TODO: what's this all about?
          nativeLongitude, // e.g. 141.145116  TODO: what's this all about?
          nativeType, // e.g. "wgs"  TODO: get acceptable values for this
          power, // e.g. 0  TODO: get acceptable values for this
          shiftState, // e.g. null  TODO: get acceptable values for this
          speed, // e.g. null  TODO: find out the units for this but my guess is imperial units (mph)
          timestamp: dsTimestamp, // e.g. 1600552117638
        },
        guiSettings: {
          gui24HourTime, // boolean
          guiChargeRateUnits, // e.g. "kW"  TODO: get acceptable values for this
          guiDistanceUnits, // e.g. "km/hr"  TODO: get acceptable values for this
          guiRangeDisplay, // e.g. "Rated"  TODO: get acceptable values for this
          guiTemperatureUnits, // e.g. "C"  TODO: get acceptable values for this
          showRangeUnits, // boolean
          timestamp: gsTimestamp, // unix epoch timestamp
        },
        vehicleState: {
          apiVersion, // e.g. 10,
          autoparkStateV2, // e.g. "standby"  TODO: get acceptable values for this
          autoparkStyle, // e.g. "standard", "dead_man"  TODO: get acceptable values for this
          calendarSupported, // boolean
          carVersion, // e.g. "2020.36.10 010e3e5a2863",
          centerDisplayState, // e.g. 0 = off, 2 = on, 3 = charging screen, 7 = sentry mode, 8 = dog mode
          df, // e.g. 0 (driver-side front tyre/someone sitting?) TODO: get acceptable values
          dr, // e.g. 0 (driver-side rear tyre/someone sitting?) TODO: get acceptable values
          fdWindow, // e.g. 0 (front driver-side window)  TODO: get acceptable values
          fpWindow, // e.g. 0 (front passenger-side window)  TODO: get acceptable values
          ft, // e.g. 0 (front trunk) TODO get acceptable values
          isUserPresent, // boolean
          lastAutoparkError, // e.g. "no_error",
          locked, // boolean
          mediaState: {
            remoteControlEnabled  // boolean
          },
          notificationsSupported, // boolean
          odometer, // e.g 16686.68661 always in imperial units (miles)
          parsedCalendarSupported, // boolean
          pf, // e.g. 0 (passenger-side front tyre/someone sitting?) TODO: get acceptable values
          pr, // e.g. 0 (passenger-side rear tyre/someone sitting?) TODO: get acceptable values
          rdWindow, // e.g. 0 (rear driver-side window)  TODO: get acceptable values
          remoteStart, // boolean
          remoteStartEnabled, // boolean
          remoteStartSupported, // boolean
          rpWindow, // e.g. 0 TODO no idea what this is (driver-side front)
          rt, // e.g. 0 (rear trunk) TODO get acceptable values
          sentryMode, // boolean
          sentryModeAvailable, // boolean
          smartSummonAvailable, // boolean
          softwareUpdate: {
            downloadPerc, // 0 if not downloading
            expectedDurationSec, // e.g. 2700 but no update downloading
            installPerc, // 1 if not installing
            status, // e.g. ''
            version, // e.g. ''
          },
          speedLimitMode: {
            active, // boolean
            currentLimitMph, // always in imperial units
            maxLimitMph, // always in imperial units
            minLimitMph, // always in imperial units
            pinCodeSet, // boolean
          },
          summonStandbyModeEnabled, // boolean
          timestamp, // numeric unix epoch time
          valetMode, // boolean
          valetPinNeeded, // boolean
          vehicleName // TODO: is this different to the displayName of the vehicle?
        }
    } = await vehicles.vehicleState({ id, token })

    vehicleState

    The car's current state (This is the same as the vehicleState field in the response to vehicles.vehicleData())

    const {
      response: {
        apiVersion, // e.g. 10 
        autoparkStateV2, // 'standby' or ? (also seeing `autoparkStateV3` in docs)
        autoparkStyle, // e.g. 'standard', 'dead_man'
        calendarSupported, // boolean
        carVersion, // e.g. '2020.36.10 010e3e5a2863'
        centreDisplayState, // e.g. 0 = off, 2 = on, 3 = charging screen, 7 = sentry mode, 8 = dog mode
        df, // driver-side front door 0 = closed, non-zero is open.
        dr, // driver-side rear door 0 = closed, non-zero is open.
        fdWindow, // e.g. 0 = closed, non-zero is open (front driver-side window) TODO is it a %?
        fpWindow, // e.g. 0 = closed, non-zero is open (front passenger-side window) TODO is it a %?
        ft, // front trunk (aka frunk) 0 = closed, non-zero is open.
        isUserPresent, // boolean
        lastAutoparkError, // 'no_error'
        locked, // boolean
        mediaState: { // see also the `mediaState` command
          remoteControlEnabled, // e.g. true. boolean
        },
        notificationsSupported, // boolean
        odometer, // NOTE always in miles not metric
        parsedCalendarSupported, // boolean
        pf, // passenger-side front door 0 = closed, non-zero is open.
        pr, // passenger-side rear door 0 = closed, non-zero is open.
        rdWindow, // e.g. 0 (rear driver-side window)
        remoteStart, // boolean
        remoteStartEnabled, // boolean
        remoteStartSupported, // boolean
        rpWindow, // e.g. 0 (rear passenger-side window)
        rt, // rear trunk (aka boot) 0 = closed, non-zero is open.
        sentryMode, // boolean
        sentryModeAvailable, // boolean
        smartSummonAvailable, // boolean
        softwareUpdate: {
          downloadPerc, // 0 if not downloading
          expectedDurationSec, // e.g. 2700 but no update downloading
          installPerc, // 1 if not installing
          status, // e.g. ''
          version, // e.g. ''
        },
        speedLimitMode; {
          active, // boolean
          currentLimitMph, // always in imperial units
          maxLimitMph, // always in imperial units
          minLimitMph, // always in imperial units
          pinCodeSet, // boolean
        },
        summonStandbyModeEnabled, // boolean
        timestamp, // numeric unix epoch time
        valetMode, // boolean
        valetPinNeeded, // boolean
        vehicleName // TODO: is this different to the displayName of the vehicle?
      }
    } = await vehicles.vehicleState({ id, token })

    vehicleConfig

    The car's configuration (This is the same as the vehicleConfig field in the response to vehicles.vehicleData())

    const {
      response: {
        canAcceptNavigationRequests, // boolean 
        canActuateTrunks, // boolean
        carSpecialType, // e.g. "base" TODO: find out these values.
        carType, // mine is a "model3"  TODO: find out these values.
        chargePortType, // mine is "CCS"  TODO: find out these values.
        eceRestrictions, // boolean
        euVehicle, // boolean (e.g. true but I am in AU)
        exteriorColor, // mine is "MidnightSilver"  TODO: find out these values.
        hasAirSuspension, // boolean
        hasLudicrousMode, // boolean
        keyVersion, // e.g. 2
        motorizedChargePort, // boolean
        plg, // boolean (e.g. false)
        rearSeatHeaters, // e.g. 1 - I have rear seat heaters
        rearSeatType, // e.g. null
        rhd, // right hand drive? (e.g. true)
        roofColor, // e.g. "Glass"  TODO: find out these values.
        seatType, // e.g. null
        spoilerType, // e.g. "None"
        sunRoofInstalled, // e.g. null,
        thirdRowSeats, // e.g. "<invalid>",  TODO: find out these values.
        timestamp, // unix epoch timestamp
        useRangeBadging, // e.g. true,
        wheelType // e.g. "Pinwheel18"  TODO: find out these values.
      }
    } = await vehicles.vehicleConfig({ id, token })

    chargeState

    The car's current charge state. (This is the same as the chargeState field in the response to vehicles.vehicleData())

    const {
      response: {
        batteryHeaterOn, // boolean 
        batteryLevel, // integer percentage
        batteryRange, // floating point value using imperial units (miles)
        chargeCurrentRequest, // how many amps the car wants (e.g. 8)
        chargeCurrentRequestMax, // how many amps the car can have (e.g. 8)
        chargeEnableRequest, // boolean
        chargeEnergyAdded, // floating point number (e.g 10.15)
        chargeLimitSoc, // integer percentage (e.g 94)
        chargeLimitSocMax, // integer percentage (e.g 100)
        chargeLimitSocMin, // integer percentage (e.g 50)
        chargeLimitSocStd, // integer percentage (e.g 90)
        chargeMilesAddedIdeal, // floating point number (e.g 41.5)
        chargeMilesAddedRated, // floating point number (e.g 41.5)
        chargePortColdWeatherMode, // boolean
        chargePortDoorOpen, // boolean
        chargePortLatch, // e.g "Engaged"  TODO: find out these values.
        chargeRate, // a number (TODO: check these values when charging the car)
        chargeToMaxRange, // boolean
        chargerActualCurrent, // a number (TODO: check these values when charging the car)
        chargerPhases, // 1 = single, 3 = three  TODO: is there such a thing as 2 phase power?
        chargerPilotCurrent, // something else measured in amps (e.g. 8)
        chargerPower, // a number (TODO: check these values when charging the car)
        chargerVoltage, // an integer (e.g 2)
        chargingState, // e.g. "Stopped"  TODO: find out these values.
        connChargeCable, // e.g. "IEC"  TODO: find out these values.
        estBatteryRange, // floating point value using imperial units (miles) (e.g. 273.36)
        fastChargerBrand, // e.g. "<invalid>"
        fastChargerPresent, // boolean
        fastChargerType, // e.g. "MCSingleWireCAN"  TODO: find out these values.
        idealBatteryRange, // floating point value using imperial units (miles) (e.g. 281.16)
        managedChargingActive, // boolean
        managedChargingStartTime, // a timestamp or null
        managedChargingUserCanceled, // boolean
        maxRangeChargeCounter, // TODO: maybe how the car knows to warn you about overcharging.
        minutesToFullCharge, // integer count (e.g 0)
        notEnoughPowerToHeat: null, // e.g. null  TODO: find out these values.
        scheduledChargingPending, // boolean
        scheduledChargingStartTime, //  unix epoch timestamp
        timeToFullCharge, // integer count (e.g 0)
        timestamp, //  unix epoch timestamp
        tripCharging, // boolean
        usableBatteryLevel, // integer percentage (e.g 93)
        userChargeEnableRequest // e.g. null  TODO: find out these values.
      }
    } = await vehicles.chargeState({ id, token })

    climateState

    The car's current climate state. (This is the same as the climateState field in the response to vehicles.vehicleData())

    const {
      response: {
        batteryHeater, // boolean 
        batteryHeaterNoPower, // e.g. null  TODO: find out these values.
        climateKeeperMode, // e.g "off"  TODO: find out these values.
        defrostMode, // e.g. 0.  TODO: find out these values.
        driverTempSetting, // e.g. 22 (uses GUI setting `guiTemperatureUnits`)
        fanStatus, // e.g. 0.  TODO: find out these values.
        insideTemp, // e.g. 16.2 (uses GUI setting `guiTemperatureUnits`)
        isAutoConditioningOn, // boolean
        isClimateOn, // boolean
        isFrontDefrosterOn, // boolean
        isPreconditioning, // boolean
        isRearDefrosterOn, // boolean
        leftTempDirection, // e.g. 326 - range is 0 to 360 presumably.
        maxAvailTemp, // e.g. 28 (uses GUI setting `guiTemperatureUnits`)
        minAvailTemp, // e.g. 15 (uses GUI setting `guiTemperatureUnits`)
        outsideTemp, // e.g. 15.5 (uses GUI setting `guiTemperatureUnits`)
        passengerTempSetting, // e.g. 22 (uses GUI setting `guiTemperatureUnits`)
        remoteHeaterControlEnabled, // boolean
        rightTempDirection // e.g. 326 - range is 0 to 360 presumably.
        seatHeaterLeft, // 0 = off, else 1, 2, or 3
        seatHeaterRearCenter, // 0 = off, else 1, 2, or 3
        seatHeaterRearLeft, // 0 = off, else 1, 2, or 3
        seatHeaterRearRight, // 0 = off, else 1, 2, or 3
        seatHeaterRight, // 0 = off, else 1, 2, or 3
        sideMirrorHeaters, // boolean
        timestamp, // unix epoch timestamp again
        wiperBladeHeater: false
      }
    } = await vehicles.climateState({ id, token })

    driveState

    The car's current location and driving state. (This is the same as the driveState field in the response to vehicles.vehicleData())

    const {
      response: {
        gpsAsOf, // unix epoch timestamp 
        heading, // e.g. 340 0 to 360 integer degrees
        latitude, // e.g. -30.336537
        longitude, // e.g. 141.145116,
        nativeLatitude, // e.g. -30.336537  TODO: what's this all about?
        nativeLocationSupported, // e.g. 1  TODO: what's this all about?
        nativeLongitude, // e.g. 141.145116  TODO: what's this all about?
        nativeType, // e.g. "wgs"  TODO: get acceptable values for this
        power, // e.g. 0  TODO: get acceptable values for this
        shiftState, // e.g. null  TODO: get acceptable values for this
        speed, // e.g. null  TODO: find out the units for this but my guess is imperial units (mph)
        timestamp // e.g. 1600552117638
      }
    } = await vehicles.driveState({ id, token })

    guiSettings

    Localisation 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())

    const {
      response: {
        gui24HourTime, // boolean 
        guiChargeRateUnits, // e.g. "kW"  TODO: get acceptable values for this
        guiDistanceUnits, // e.g. "km/hr"  TODO: get acceptable values for this
        guiRangeDisplay, // e.g. "Rated"  TODO: get acceptable values for this
        guiTemperatureUnits, // e.g. "C"  TODO: get acceptable values for this
        showRangeUnits, // boolean
        timestamp: gsTimestamp // unix epoch timestamp
      }
    } = await vehicles.guiSettings({ id, token })

    mobileEnabled

    Is mobile access enabled?

    const { response: mobileEnabled } = await vehicles.mobileEnabled({ id, token })

    serviceData

    Current servicing data.

    const {
      response: {
        // unknown fields - maybe only of use when the car is booked in for service. 
        ...serviceData
      }
    } = await vehicles.serviceData({ id, token })

    nearbyChargingSites

    Lists Tesla-operated charging stations near to the car.

    const {
      response: {
        congestionSyncTimeUtcSecs, // integer number of seconds 
        destinationCharging: [
          {
            location: {
              lat: dcLat, //  e.g. -35.312247
              long: dcLong, // e.g. 149.133236
            },
            name: dcName, // e.g. "Hotel Realm Canberra"
            type: dcType, // e.g. "destination"
            distanceMiles: dcDist // e.g. 11.807002
          }
        ],
        superchargers: [
          {
            location: {
              lat: scLat, // e.g. -35.294304,
              long: scLong, // e.g. 149.190322
            },
            name: scName, // e.g. "Canberra, ACT"
            type: scType, // e.g. "supercharger"
            distanceMiles: scDist, // e.g. 11.87435
            availableStalls, // e.g. 5
            totalStalls, // e.g. 6
            siteClosed // boolean
          }
        ],
        "timestamp" // unix epoch timestamp
      }
    } = await vehicles.nearbyChargingSites({ id, token })

    upcomingCalendarEntries

    If you have allowed your car to share your calendar then this will list your upcoming calendar entries.

    const {
      response: { result, reason } 
    } = await vehicles.upcomingCalendarEntries({ id, token })

    Commands

    It'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.

    Commands all return a response with a result (boolean) and, if the result is false, a reason string.


    honkHorn

    Beeps the car's horn. toot!

    const {
      response: { result, reason } 
    } = await vehicles.honkHorn({ id, token })

    flashLights

    Flashes the car's headlights.

    const {
      response: { result, reason } 
    } = await vehicles.flashLights({ id, token })

    autoConditioningStart

    Start 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.

    const {
      response: { result, reason } 
    } = await vehicles.autoConditioningStart({ id, token })

    autoConditioningStop

    Stop the car's climate control system.

    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' }.

    const {
      response: { result, reason } 
    } = await vehicles.autoConditioningStop({ id, token })

    setTemps

    Sets the temperature for the car's climate control system.

    The 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.

    Notes
    • The values for driverTemp and passengerTemp are always in Metric (¬įC) no matter what you have set in guiSettings.
    • If you set the temperature very low or very high the HVAC system will start heating or cooling immediately.
    const driverTemp = 23.4 // degrees celsius.
    const {
      response: { result, reason } 
    } = await vehicles.setTemps({ id, token, driverTemp })

    setPreconditoningMax

    Toggles the climate controls between Max Defrost and the previous setting.

    You can pass on: true, or 'on: false' to this multiple times, without error.

    const {
      response: { result, reason } 
    } = await vehicles.setPreconditioningMax({ id, token, on: true })

    setSeatHeater

    Sets the seat heater level for the nominated seat.

    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.

    Value Seat
    0 front left
    1 front right
    2 rear left
    3 rear center
    4 rear right
    const {
      response: { result, reason } 
    } = await vehicles.setSeatHeater({ id, token, heater: 0, level: 1 })

    setSteeringWheelHeater

    Turns the steering wheel heater on or off.

    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 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.

    const {
      response: { result, reason } 
    } = await vehicles.setSteeringWheelHeater({ id, token, on: true }) // or on: false

    mediaTogglePlayback

    Either toggles the media between playing and paused, or if the car is tuned to a radio station, this mutes or un-mutes the audio.

    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.

    const {
      response: { result, reason } 
    } = await vehicles.mediaTogglePlayback({ id, token })

    mediaNextTrack

    Skips the media to the next track, unless the car is tuned to a radio station.

    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.

    const {
      response: { result, reason } 
    } = await vehicles.mediaNextTrack({ id, token })

    mediaPrevTrack

    Skips the media to the previous track, unless the car is tuned to a radio station.

    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.

    const {
      response: { result, reason } 
    } = await vehicles.mediaPrevTrack({ id, token })

    mediaNextFav

    Skips 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.

    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.

    const {
      response: { result, reason } 
    } = await vehicles.mediaNextFav({ id, token })

    mediaPrevFav

    Skips 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.

    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.

    const {
      response: { result, reason } 
    } = await vehicles.mediaPrevFav({ id, token })

    mediaVolumeUp

    Turns the volume up.

    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.

    const {
      response: { result, reason } 
    } = await vehicles.mediaVolumeUp({ id, token })

    mediaVolumeDown

    Turns the volume down.

    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.

    const {
      response: { result, reason } 
    } = await vehicles.mediaVolumeDown({ id, token })

    share

    Share 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.

    If the car can't understand the value you send it will return an error.

    const value = '1 Commonwealth Avenue, Yarralumla ACT 2600, Australia'
     
    const {
      response: { result, reason } 
    } = await vehicles.share({ id, token, value, locale: 'en-AU' }) // locale is optional, it will default to your OS's system locale.

    setSentryMode

    Turn sentry mode on or off.

    const {
      response: { result, reason } 
    } = await vehicles.setSentryMode({ id, token, on: true }) // or `on: false` for off.

    actuateTrunk

    Opens (or 'pops' depending on your hardware) the 'frunk' or boot.

    const {
      response: { result, reason } 
    } = await vehicles.actuateTrunk({ id, token, which: 'front' }) // for the 'frunk', or `which: 'rear'` for the boot.

    windowControl

    Lets you 'vent' or 'close' the car's windows.

    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.

    const {
      response: { result, reason } 
    } = await vehicles.windowControl({ id, token, command: 'vent' })

    or

    const {
      response: { result, reason } 
    } = await vehicles.windowControl({ id, token, command: 'close', lat: -35.297476, lon: 149.12579 })

    sunRoofControl

    Lets you 'vent' or 'close' the car's sun roof if it has a sun roof.

    const {
      response: { result, reason } 
    } = await vehicles.sunRoofControl({ id, token, state: 'vent' })

    triggerHomelink

    Lets you trigger the HomeLink controller if it is connected.

    Note You must also provide a gps location that's close to the homelink device.

    const {
      response: { result, reason } 
    } = await vehicles.triggerHomelink({ id, token, lat: -35.297476, lon: 149.12579 })

    scheduleSoftwareUpdate

    If 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.

    If there is no software update available you'll get a result: false and reason: update_not_available.

    const {
      response: { result, reason } 
    } = await vehicles.scheduleSoftwareUpdate({ id, token })

    or, to install in an hour:

    const {
      response: { result, reason } 
    } = await vehicles.scheduleSoftwareUpdate({ id, token, offset: 3600 }) // offset is in seconds

    cancelSoftwareUpdate

    If you have a pending software update, and you've scheduled an installation time, then this lets you cancel that installation.

    If there is no software update scheduled you'll get a result: false and reason: no_update_scheduled.

    const {
      response: { result, reason } 
    } = await vehicles.cancelSoftwareUpdate({ id, token })

    setValetMode

    Valet 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.

    It also hides your favourites, as well as your home, and work locations in navigation.

    If 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.

    const {
      response: { result, reason } 
    } = await vehicles.setValetMode({ id, token, on: true, password: 1234 })

    resetValetPin

    Clears the Valet Mode PIN, meaning that once Valet Mode is disabled, you can enable it with or without a new PIN.

    const {
      response: { result, reason } 
    } = await vehicles.resetValetPin({ id, token })

    logs

    Using 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.

    const { logs } = require('node-tesla-api')

    getEntitlements

    Does your token allow you to perform diagnostics?

    const {
      response: { eligible } // eligible will be true or false 
    } = await logs.getEntitlements({ token })

    getLogs

    If you are eligible for logs you can get the account logs associated with your token. hint you probably are not eligible.

    const {
      response: { result, reason } 
    } = await logs.getLogs({ token })
    • On timdorr: not listed
    • On teslaapi: logs/logs

    sendEntitlements

    It's hard to know what this does.

    const {
      response: { result, reason } 
    } = await logs.sendEntitlements({ token })

    Development

    branch status coverage audit notes
    develop CircleCI codecov Vulnerabilities work in progress
    master CircleCI codecov Vulnerabilities latest stable release

    Prerequisites

    • NodeJS, version 12.19.0 (LTS) or better (I use nvm to manage Node versions ‚ÄĒ brew install nvm.)

    Install dependencies

    npm install

    Linting

    npm run lint

    Note this will also run whenever you commit file changes.

    Formatting via Prettier

    npm run prettier

    Note: this will also run whenever you commit file changes.

    Testing

    npm test

    or with code coverage

    npm run test:unit:cov

    Contributing

    Please see the contributing notes.

    To Do

    • Cross check the API with the latest updates
    • Add API unit tests and bring test coverage to 100%
    • DRY up the code some more
    • Improve documentation

    Keywords

    Install

    npm i node-tesla-api

    DownloadsWeekly Downloads

    1

    Version

    0.1.0

    License

    MIT

    Unpacked Size

    110 kB

    Total Files

    85

    Last publish

    Collaborators

    • avatar