├── .jshintignore ├── PULL_REQUEST_TEMPLATE.md ├── .travis.yml ├── .github ├── FUNDING.yml ├── dependabot.yml ├── workflows │ ├── greetings.yml │ └── codeql-analysis.yml └── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── winlint.cmd ├── .jshintrc ├── docgen.cmd ├── wintest.cmd ├── .gitignore ├── CONTRIBUTING.md ├── samples ├── logout.js ├── products.js ├── lock.js ├── startCharge.js ├── stopCharge.js ├── climateStart.js ├── climateStop.js ├── honkHorn.js ├── openChargePort.js ├── resetValetPin.js ├── unlock.js ├── flashLights.js ├── wakeup.js ├── mobileEnabled.js ├── setSpeed.js ├── remoteStart.js ├── cancelUpdate.js ├── setTemps.js ├── simpleStreaming.js ├── openTrunk.js ├── calendar.js ├── odometer.js ├── valet.js ├── sunroof.js ├── scheduleUpdate.js ├── setChargeLimit.js ├── guiSettings.js ├── login.js ├── navRequest.js ├── homelink.js ├── vehicleConfig.js ├── climate.js ├── media.js ├── geoloc.js ├── sampleFramework.js ├── vehicle.js └── soc.js ├── LICENSE ├── MIGRATION.md ├── package.json ├── CODE_OF_CONDUCT.md ├── src └── auth.js ├── CHANGELOG.md ├── teslajs.min.js ├── README.md └── apiary.apib /.jshintignore: -------------------------------------------------------------------------------- 1 | samples/public 2 | samples/views 3 | samples/routes 4 | -------------------------------------------------------------------------------- /PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Fixes # . 2 | 3 | Changes proposed in this pull request: 4 | * 5 | * 6 | * 7 | 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "node" 4 | os: 5 | - linux 6 | env: 7 | global: 8 | - TESLAJS_USER=elon@tesla.com 9 | - TESLAJS_PASS=password 10 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: mseminatore 4 | custom: "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=26QPDTC76PBLA&source=url" 5 | -------------------------------------------------------------------------------- /winlint.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | echo================================= Lint ========================================== 4 | cmd /c ".\node_modules\.bin\jshint" teslajs.js samples/ 5 | echo================================================================================= -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "curly": true, 3 | "eqeqeq": false, 4 | "lastsemic": true, 5 | "nocomma": true, 6 | "nonew": true, 7 | "undef": true, 8 | "unused": "vars", 9 | "varstmt": false, 10 | "asi": true, 11 | "strict": "global", 12 | "node": true 13 | } 14 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: npm 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | time: "13:00" 8 | open-pull-requests-limit: 10 9 | ignore: 10 | - dependency-name: ws 11 | versions: 12 | - 7.4.3 13 | -------------------------------------------------------------------------------- /docgen.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | echo========================== Generating Docs ================================ 4 | cmd /c ".\node_modules\.bin\jsdoc2md" teslajs.js > docs\DOCS.md 5 | echo ..Documentation generated.. 6 | echo=========================================================================== 7 | -------------------------------------------------------------------------------- /.github/workflows/greetings.yml: -------------------------------------------------------------------------------- 1 | name: Greetings 2 | 3 | on: [pull_request, issues] 4 | 5 | jobs: 6 | greeting: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/first-interaction@v1 10 | with: 11 | repo-token: ${{ secrets.GITHUB_TOKEN }} 12 | issue-message: 'Thank you for reporting this issue!' 13 | pr-message: 'Thank you for this pull request!' 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | **Is your feature request related to a problem? Please describe.** 8 | A clear and concise description of the problem. 9 | 10 | **Describe the solution you'd like** 11 | A clear and concise description of what you want to happen. 12 | 13 | **Additional context** 14 | Add any other context or screenshots about the feature request here. 15 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | 5 | --- 6 | 7 | **Describe the bug** 8 | A clear and concise description of the bug or unexpected behavior. 9 | 10 | **Steps To Reproduce** 11 | Identify the steps to reproduce the behavior: 12 | 1. Go to '...' 13 | 2. Click on '....' 14 | 3. Scroll down to '....' 15 | 4. See error 16 | 17 | **Expected behavior** 18 | A clear and concise description of what you expected to happen. 19 | 20 | **Library version** 21 | Please report the version of the library that experienced the issue. 22 | 23 | **Additional context** 24 | Add any other context about the problem here. 25 | -------------------------------------------------------------------------------- /wintest.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | call winlint.cmd 4 | echo. 5 | echo================================ Testing ======================================== 6 | call "./node_modules/.bin/istanbul" cover "./node_modules/mocha/bin/_mocha" --report lcovonly -- -R spec 7 | echo. 8 | echo================================= Coverage ====================================== 9 | type ".\coverage\lcov.info" | node ".\node_modules\coveralls\bin\coveralls.js" 10 | echo================================================================================= 11 | echo. 12 | echo================================================================================= 13 | echo *** All Done! *** 14 | echo================================================================================= 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # IntelliJ files 2 | .idea 3 | 4 | # VS Code files 5 | .vscode 6 | 7 | # Logs 8 | logs 9 | *.log 10 | npm-debug.log* 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | 17 | # Directory for instrumented libs generated by jscoverage/JSCover 18 | lib-cov 19 | 20 | # Coverage directory used by tools like istanbul 21 | coverage 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # node-waf configuration 27 | .lock-wscript 28 | 29 | # Compiled binary addons (http://nodejs.org/api/addons.html) 30 | build/Release 31 | 32 | # Dependency directory 33 | node_modules 34 | 35 | # Optional npm cache directory 36 | .npm 37 | 38 | # Test file directory 39 | fixtures 40 | 41 | # Code Coverage files 42 | .coveralls.yml 43 | 44 | # Optional REPL history 45 | .node_repl_history 46 | 47 | # development files 48 | todo.txt 49 | tjs.js 50 | .token 51 | setenv.cmd 52 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing code via PR 2 | 3 | Code contributions are welcome, particularly bug fixes and enhancements! `Pull 4 | Requests` will be considered with the following criteria: 5 | 6 | 1. Must pass both `npm test` and `wintest` tests 7 | 2. Should make every effort meet or exceed current code coverage level 8 | 3. Must respect and align to Project Principles (see [README.md](https://github.com/mseminatore/TeslaJS/blob/master/README.md)) 9 | 4. Must add general value to the project 10 | 5. Must update appropriate documentation 11 | 6. New functionality should be demonstrated in a new or updated sample 12 | 13 | > Note that the Project owners reserve the right to accept or reject any PR 14 | > for any reason. 15 | 16 | ## Filing Issues 17 | 18 | Useful bug reports include the following: 19 | 20 | * Version of the library used (ideally the latest published version) 21 | * Clear set of steps used to reproduct the issue 22 | * Code examples if appropriate 23 | -------------------------------------------------------------------------------- /samples/logout.js: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // This sample demonstrates using TeslaJS 3 | // 4 | // https://github.com/mseminatore/TeslaJS 5 | // 6 | // Copyright (c) 2016 Mark Seminatore 7 | // 8 | // Refer to included LICENSE file for usage rights and restrictions 9 | //===================================================================== 10 | "use strict"; 11 | 12 | var tjs = require('../teslajs'); 13 | var fs = require('fs'); 14 | 15 | // 16 | // 17 | // 18 | var tokenFound = false; 19 | 20 | try { 21 | tokenFound = fs.statSync('.token').isFile(); 22 | } catch (e) { 23 | } 24 | 25 | if (tokenFound) { 26 | var token = JSON.parse(fs.readFileSync('.token', 'utf8')); 27 | 28 | // attempt to delete the locally cached Auth token 29 | try { 30 | fs.unlinkSync('.token'); 31 | console.log("Token file successfully deleted."); 32 | } catch (e) { 33 | } 34 | 35 | tjs.logout(token, function (err, result) { 36 | console.log(result); 37 | }); 38 | } 39 | 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Mark Seminatore 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /samples/products.js: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // This sample demonstrates using TeslaJS 3 | // 4 | // https://github.com/mseminatore/TeslaJS 5 | // 6 | // Copyright (c) 2016 Mark Seminatore 7 | // 8 | // Refer to included LICENSE file for usage rights and restrictions 9 | //===================================================================== 10 | "use strict"; 11 | 12 | require('colors'); 13 | var program = require('commander'); 14 | var framework = require('./sampleFramework.js'); 15 | 16 | // 17 | // 18 | // 19 | program 20 | .option('-u, --username [string]', 'username (needed only if token not cached)') 21 | .option('-p, --password [string]', 'password (needed only if token not cached)') 22 | .option('-U, --uri [string]', 'URI of test server (e.g. http://127.0.0.1:3000)') 23 | .option('-v, --verbose', 'show detailed results') 24 | .parse(process.argv); 25 | 26 | // 27 | var sample = new framework.SampleFramework(program, sampleMain); 28 | sample.run(); 29 | 30 | // 31 | // 32 | // 33 | function sampleMain(tjs, options) { 34 | tjs.productsAsync(options).then( function(products) { 35 | console.log("\nTesla products returned: " + products.length + "\n"); 36 | 37 | if (program.verbose) { 38 | console.log(products); 39 | } 40 | }); 41 | } 42 | -------------------------------------------------------------------------------- /MIGRATION.md: -------------------------------------------------------------------------------- 1 | # TeslaJS Migration Buid 2 | 3 | ## V3.x to V4.x 4 | 5 | Unfortunately we learned recently that npm does not respect case-sensitive file systems. 6 | As a result on Mac and Linux if you: 7 | 8 | npm install teslajs 9 | 10 | as the library documentation suggests, npm will install the library under node_modules 11 | into a directory called `teslajs`. This will break calls to `require("TeslaJS")`. 12 | However, if you instead: 13 | 14 | npm install TeslaJS 15 | 16 | npm will install the library under node_modules into a directory called `TeslaJS`. 17 | This will work correctly with `require("TelsaJS")`. It seems the right solution is 18 | to attempt to remove case issues from the equation. 19 | 20 | Unfortunately the rules of `semver` say this is a breaking change, thus the bump 21 | from 3.x to 4.x. So the **big** change from 3.x to 4.x is simply to update all `require` 22 | statements to use all lower-case as in: 23 | 24 | npm install teslajs 25 | ... 26 | require('teslajs'); 27 | 28 | Since I was removing case from the equation I also renamed the `Examples` dir to 29 | be `samples` instead. 30 | 31 | Apologies for the churn! 32 | 33 | ## V2.x to V3.x 34 | 35 | The primary breaking change in V3.x compared to 2.x is the API renaming change of 36 | `allVehicles()` to `vehicles()` and `vehicles()` to `vehicle()`. -------------------------------------------------------------------------------- /samples/lock.js: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // This sample demonstrates using TeslaJS 3 | // 4 | // https://github.com/mseminatore/TeslaJS 5 | // 6 | // Copyright (c) 2016 Mark Seminatore 7 | // 8 | // Refer to included LICENSE file for usage rights and restrictions 9 | //===================================================================== 10 | "use strict"; 11 | 12 | require('colors'); 13 | var program = require('commander'); 14 | var framework = require('./sampleFramework.js'); 15 | 16 | // 17 | // 18 | // 19 | program 20 | .option('-u, --username [string]', 'username (needed only if token not cached)') 21 | .option('-p, --password [string]', 'password (needed only if token not cached)') 22 | .option('-i, --index ', 'vehicle index (first car by default)', parseInt) 23 | .option('-U, --uri [string]', 'URI of test server (e.g. http://127.0.0.1:3000)') 24 | .parse(process.argv); 25 | 26 | // 27 | var sample = new framework.SampleFramework(program, sampleMain); 28 | sample.run(); 29 | 30 | // 31 | // 32 | // 33 | function sampleMain(tjs, options) { 34 | tjs.doorLock(options, function (err, result) { 35 | if (err) { 36 | console.log("Door lock failed!".red); 37 | return; 38 | } 39 | 40 | console.log("\nThe doors are now: " + "LOCKED".bgGreen); 41 | }); 42 | } 43 | -------------------------------------------------------------------------------- /samples/startCharge.js: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // This sample demonstrates using TeslaJS 3 | // 4 | // https://github.com/mseminatore/TeslaJS 5 | // 6 | // Copyright (c) 2016 Mark Seminatore 7 | // 8 | // Refer to included LICENSE file for usage rights and restrictions 9 | //===================================================================== 10 | "use strict"; 11 | 12 | require('colors'); 13 | var program = require('commander'); 14 | var framework = require('./sampleFramework.js'); 15 | 16 | // 17 | // 18 | // 19 | program 20 | .option('-u, --username [string]', 'username (needed only if token not cached)') 21 | .option('-p, --password [string]', 'password (needed only if token not cached)') 22 | .option('-i, --index ', 'vehicle index (first car by default)', parseInt) 23 | .option('-U, --uri [string]', 'URI of test server (e.g. http://127.0.0.1:3000)') 24 | .parse(process.argv); 25 | 26 | // 27 | var sample = new framework.SampleFramework(program, sampleMain); 28 | sample.run(); 29 | 30 | // 31 | // 32 | // 33 | function sampleMain(tjs, options) { 34 | tjs.startCharge(options, function (err, result) { 35 | if (result.result) { 36 | console.log("\nCharging will begin shortly!"); 37 | } else { 38 | console.log(result.reason.red); 39 | } 40 | }); 41 | } 42 | -------------------------------------------------------------------------------- /samples/stopCharge.js: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // This sample demonstrates using TeslaJS 3 | // 4 | // https://github.com/mseminatore/TeslaJS 5 | // 6 | // Copyright (c) 2016 Mark Seminatore 7 | // 8 | // Refer to included LICENSE file for usage rights and restrictions 9 | //===================================================================== 10 | "use strict"; 11 | 12 | require('colors'); 13 | var program = require('commander'); 14 | var framework = require('./sampleFramework.js'); 15 | 16 | // 17 | // 18 | // 19 | program 20 | .option('-u, --username [string]', 'username (needed only if token not cached)') 21 | .option('-p, --password [string]', 'password (needed only if token not cached)') 22 | .option('-i, --index ', 'vehicle index (first car by default)', parseInt) 23 | .option('-U, --uri [string]', 'URI of test server (e.g. http://127.0.0.1:3000)') 24 | .parse(process.argv); 25 | 26 | // 27 | var sample = new framework.SampleFramework(program, sampleMain); 28 | sample.run(); 29 | 30 | // 31 | // 32 | // 33 | function sampleMain(tjs, options) { 34 | tjs.stopCharge(options, function (err, result) { 35 | if (result.result) { 36 | console.log("\nCharging will stop shortly!"); 37 | } else { 38 | console.log(result.reason.red); 39 | } 40 | }); 41 | } 42 | -------------------------------------------------------------------------------- /samples/climateStart.js: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // This sample demonstrates using TeslaJS 3 | // 4 | // https://github.com/mseminatore/TeslaJS 5 | // 6 | // Copyright (c) 2016 Mark Seminatore 7 | // 8 | // Refer to included LICENSE file for usage rights and restrictions 9 | //===================================================================== 10 | "use strict"; 11 | 12 | require('colors'); 13 | var program = require('commander'); 14 | var framework = require('./sampleFramework.js'); 15 | 16 | // 17 | // 18 | // 19 | program 20 | .option('-u, --username [string]', 'username (needed only if token not cached)') 21 | .option('-p, --password [string]', 'password (needed only if token not cached)') 22 | .option('-i, --index ', 'vehicle index (first car by default)', parseInt) 23 | .option('-U, --uri [string]', 'URI of test server (e.g. http://127.0.0.1:3000)') 24 | .parse(process.argv); 25 | 26 | // 27 | var sample = new framework.SampleFramework(program, sampleMain); 28 | sample.run(); 29 | 30 | // 31 | // 32 | // 33 | function sampleMain(tjs, options) { 34 | tjs.climateStart(options, function (err, result) { 35 | if (result.result) { 36 | console.log("\nClimate is now: " + "ON".green); 37 | } else { 38 | console.log(result.reason.red); 39 | } 40 | }); 41 | } 42 | -------------------------------------------------------------------------------- /samples/climateStop.js: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // This sample demonstrates using TeslaJS 3 | // 4 | // https://github.com/mseminatore/TeslaJS 5 | // 6 | // Copyright (c) 2016 Mark Seminatore 7 | // 8 | // Refer to included LICENSE file for usage rights and restrictions 9 | //===================================================================== 10 | "use strict"; 11 | 12 | require('colors'); 13 | var program = require('commander'); 14 | var framework = require('./sampleFramework.js'); 15 | 16 | // 17 | // 18 | // 19 | program 20 | .option('-u, --username [string]', 'username (needed only if token not cached)') 21 | .option('-p, --password [string]', 'password (needed only if token not cached)') 22 | .option('-i, --index ', 'vehicle index (first car by default)', parseInt) 23 | .option('-U, --uri [string]', 'URI of test server (e.g. http://127.0.0.1:3000)') 24 | .parse(process.argv); 25 | 26 | // 27 | var sample = new framework.SampleFramework(program, sampleMain); 28 | sample.run(); 29 | 30 | // 31 | // 32 | // 33 | function sampleMain(tjs, options) { 34 | tjs.climateStop(options, function (err, result) { 35 | if (result.result) { 36 | console.log("\nClimate is now: " + "OFF".green); 37 | } else { 38 | console.log(result.reason.red); 39 | } 40 | }); 41 | } 42 | -------------------------------------------------------------------------------- /samples/honkHorn.js: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // This sample demonstrates using TeslaJS 3 | // 4 | // https://github.com/mseminatore/TeslaJS 5 | // 6 | // Copyright (c) 2016 Mark Seminatore 7 | // 8 | // Refer to included LICENSE file for usage rights and restrictions 9 | //===================================================================== 10 | "use strict"; 11 | 12 | require('colors'); 13 | var program = require('commander'); 14 | var framework = require('./sampleFramework.js'); 15 | 16 | // 17 | // 18 | // 19 | program 20 | .option('-u, --username [string]', 'username (needed only if token not cached)') 21 | .option('-p, --password [string]', 'password (needed only if token not cached)') 22 | .option('-U, --uri [string]', 'URI of test server (e.g. http://127.0.0.1:3000)') 23 | .option('-i, --index ', 'vehicle index (first car by default)', parseInt) 24 | .parse(process.argv); 25 | 26 | // 27 | var sample = new framework.SampleFramework(program, sampleMain); 28 | sample.run(); 29 | 30 | // 31 | // 32 | // 33 | function sampleMain(tjs, options) { 34 | tjs.honkHorn(options, function (err, result) { 35 | if (result.result) { 36 | console.log("\nDid you hear it?! " + "beep beep".green); 37 | } else { 38 | console.log(result.reason.red); 39 | } 40 | }); 41 | } 42 | -------------------------------------------------------------------------------- /samples/openChargePort.js: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // This sample demonstrates using TeslaJS 3 | // 4 | // https://github.com/mseminatore/TeslaJS 5 | // 6 | // Copyright (c) 2016 Mark Seminatore 7 | // 8 | // Refer to included LICENSE file for usage rights and restrictions 9 | //===================================================================== 10 | "use strict"; 11 | 12 | require('colors'); 13 | var program = require('commander'); 14 | var framework = require('./sampleFramework.js'); 15 | 16 | // 17 | // 18 | // 19 | program 20 | .option('-u, --username [string]', 'username (needed only if token not cached)') 21 | .option('-p, --password [string]', 'password (needed only if token not cached)') 22 | .option('-i, --index ', 'vehicle index (first car by default)', parseInt) 23 | .option('-U, --uri [string]', 'URI of test server (e.g. http://127.0.0.1:3000)') 24 | .parse(process.argv); 25 | 26 | // 27 | var sample = new framework.SampleFramework(program, sampleMain); 28 | sample.run(); 29 | 30 | // 31 | // 32 | // 33 | function sampleMain(tjs, options) { 34 | tjs.openChargePort(options, function (err, result) { 35 | if (result) { 36 | console.log("\nCharge port: " + "OPEN".green); 37 | } else { 38 | console.error("Error opening port!".red); 39 | } 40 | }); 41 | } 42 | -------------------------------------------------------------------------------- /samples/resetValetPin.js: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // This sample demonstrates using TeslaJS 3 | // 4 | // https://github.com/mseminatore/TeslaJS 5 | // 6 | // Copyright (c) 2016 Mark Seminatore 7 | // 8 | // Refer to included LICENSE file for usage rights and restrictions 9 | //===================================================================== 10 | "use strict"; 11 | 12 | require('colors'); 13 | var program = require('commander'); 14 | var framework = require('./sampleFramework.js'); 15 | 16 | // 17 | // 18 | // 19 | program 20 | .option('-u, --username [string]', 'username (needed only if token not cached)') 21 | .option('-p, --password [string]', 'password (needed only if token not cached)') 22 | .option('-i, --index ', 'vehicle index (first car by default)', parseInt) 23 | .option('-U, --uri [string]', 'URI of test server (e.g. http://127.0.0.1:3000)') 24 | .parse(process.argv); 25 | 26 | // 27 | var sample = new framework.SampleFramework(program, sampleMain); 28 | sample.run(); 29 | 30 | // 31 | // 32 | // 33 | function sampleMain(tjs, options) { 34 | tjs.resetValetPin(options, function (err, result) { 35 | if (result.result) { 36 | console.log("\nPIN reset completed successfully!"); 37 | } else { 38 | console.log(result.reason.red); 39 | } 40 | }); 41 | } 42 | -------------------------------------------------------------------------------- /samples/unlock.js: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // This sample demonstrates using TeslaJS 3 | // 4 | // https://github.com/mseminatore/TeslaJS 5 | // 6 | // Copyright (c) 2016 Mark Seminatore 7 | // 8 | // Refer to included LICENSE file for usage rights and restrictions 9 | //===================================================================== 10 | "use strict"; 11 | 12 | require('colors'); 13 | var program = require('commander'); 14 | var framework = require('./sampleFramework.js'); 15 | 16 | // 17 | // 18 | // 19 | program 20 | .option('-u, --username [string]', 'username (needed only if token not cached)') 21 | .option('-p, --password [string]', 'password (needed only if token not cached)') 22 | .option('-i, --index ', 'vehicle index (first car by default)', parseInt) 23 | .option('-U, --uri [string]', 'URI of test server (e.g. http://127.0.0.1:3000)') 24 | .parse(process.argv); 25 | 26 | // 27 | var sample = new framework.SampleFramework(program, sampleMain); 28 | sample.run(); 29 | 30 | // 31 | // 32 | // 33 | function sampleMain(tjs, options) { 34 | tjs.doorUnlock(options, function (err, result) { 35 | if (err) { 36 | console.log("Door unlock failed!".red); 37 | return; 38 | } 39 | 40 | console.log("\nThe doors are now: " + "UNLOCKED".bgRed); 41 | }); 42 | } 43 | -------------------------------------------------------------------------------- /samples/flashLights.js: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // This sample demonstrates using TeslaJS 3 | // 4 | // https://github.com/mseminatore/TeslaJS 5 | // 6 | // Copyright (c) 2016 Mark Seminatore 7 | // 8 | // Refer to included LICENSE file for usage rights and restrictions 9 | //===================================================================== 10 | "use strict"; 11 | 12 | require('colors'); 13 | var program = require('commander'); 14 | var framework = require('./sampleFramework.js'); 15 | 16 | // 17 | // 18 | // 19 | program 20 | .option('-u, --username [string]', 'username (needed only if token not cached)') 21 | .option('-p, --password [string]', 'password (needed only if token not cached)') 22 | .option('-i, --index ', 'vehicle index (first car by default)', parseInt) 23 | .option('-U, --uri [string]', 'URI of test server (e.g. http://127.0.0.1:3000)') 24 | .parse(process.argv); 25 | 26 | // 27 | var sample = new framework.SampleFramework(program, sampleMain); 28 | sample.run(); 29 | 30 | // 31 | // 32 | // 33 | function sampleMain(tjs, options) { 34 | tjs.flashLights(options, function (err, result) { 35 | if (result.result) { 36 | console.log("\nWere you watching?! " + "flash!".bold.green); 37 | } else { 38 | console.log(result.reason.red); 39 | } 40 | }); 41 | } 42 | -------------------------------------------------------------------------------- /samples/wakeup.js: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // This sample demonstrates using TeslaJS 3 | // 4 | // https://github.com/mseminatore/TeslaJS 5 | // 6 | // Copyright (c) 2016 Mark Seminatore 7 | // 8 | // Refer to included LICENSE file for usage rights and restrictions 9 | //===================================================================== 10 | "use strict"; 11 | 12 | require('colors'); 13 | var program = require('commander'); 14 | var framework = require('./sampleFramework.js'); 15 | 16 | // 17 | // 18 | // 19 | program 20 | .option('-u, --username [string]', 'username (needed only if token not cached)') 21 | .option('-p, --password [string]', 'password (needed only if token not cached)') 22 | .option('-i, --index ', 'vehicle index (first car by default)', parseInt) 23 | .option('-U, --uri [string]', 'URI of test server (e.g. http://127.0.0.1:3000)') 24 | .parse(process.argv); 25 | 26 | // 27 | var sample = new framework.SampleFramework(program, sampleMain); 28 | sample.run(); 29 | 30 | // 31 | // 32 | // 33 | function sampleMain(tjs, options) { 34 | tjs.wakeUp(options, function (err, result) { 35 | if (err) { 36 | console.error("\nWakeUp command: " + "Failed!".red); 37 | } else { 38 | console.log("\nWakeUp command: " + "Succeeded".green); 39 | console.log("Vehicle state: " + result.state.green); 40 | } 41 | }); 42 | } 43 | -------------------------------------------------------------------------------- /samples/mobileEnabled.js: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // This sample demonstrates using TeslaJS 3 | // 4 | // https://github.com/mseminatore/TeslaJS 5 | // 6 | // Copyright (c) 2016 Mark Seminatore 7 | // 8 | // Refer to included LICENSE file for usage rights and restrictions 9 | //===================================================================== 10 | "use strict"; 11 | 12 | require('colors'); 13 | var program = require('commander'); 14 | var framework = require('./sampleFramework.js'); 15 | 16 | // 17 | // 18 | // 19 | program 20 | .option('-u, --username [string]', 'username (needed only if token not cached)') 21 | .option('-p, --password [string]', 'password (needed only if token not cached)') 22 | .option('-i, --index ', 'vehicle index (first car by default)', parseInt) 23 | .option('-U, --uri [string]', 'URI of test server (e.g. http://127.0.0.1:3000)') 24 | .parse(process.argv); 25 | 26 | // 27 | var sample = new framework.SampleFramework(program, sampleMain); 28 | sample.run(); 29 | 30 | // 31 | // 32 | // 33 | function sampleMain(tjs, options) { 34 | tjs.mobileEnabled(options, function (err, result) { 35 | if (!result) { 36 | console.error("\nError: " + "No response to mobileEnabled() query!".red); 37 | return; 38 | } 39 | 40 | var str = "DISABLED".red; 41 | if (result) { 42 | str = "ENABLED".green; 43 | } 44 | 45 | console.log("\nMobile access is: " + str); 46 | }); 47 | } 48 | -------------------------------------------------------------------------------- /samples/setSpeed.js: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // This sample demonstrates using TeslaJS 3 | // 4 | // https://github.com/mseminatore/TeslaJS 5 | // 6 | // Copyright (c) 2016 Mark Seminatore 7 | // 8 | // Refer to included LICENSE file for usage rights and restrictions 9 | //===================================================================== 10 | "use strict"; 11 | 12 | require('colors'); 13 | var program = require('commander'); 14 | var framework = require('./sampleFramework.js'); 15 | 16 | // 17 | // 18 | // 19 | program 20 | .usage('[options] speed') 21 | .option('-u, --username [string]', 'username (needed only if token not cached)') 22 | .option('-p, --password [string]', 'password (needed only if token not cached)') 23 | .option('-i, --index ', 'vehicle index (first car by default)', parseInt) 24 | .option('-U, --uri [string]', 'URI of test server (e.g. http://127.0.0.1:3000)') 25 | .parse(process.argv); 26 | 27 | // 28 | var sample = new framework.SampleFramework(program, sampleMain); 29 | sample.run(); 30 | 31 | // 32 | // 33 | // 34 | function sampleMain(tjs, options) { 35 | var speed = program.args[0]; 36 | if (!speed) { 37 | program.help(); 38 | } 39 | 40 | tjs.speedLimitSetLimit(options, speed, function (err, result) { 41 | if (result.result) { 42 | var str = (speed + " MPH").green; 43 | console.log("\nSpeed limit successfully set to: " + str); 44 | } else { 45 | console.log(result.reason.red); 46 | } 47 | }); 48 | } 49 | -------------------------------------------------------------------------------- /samples/remoteStart.js: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // This sample demonstrates using TeslaJS 3 | // 4 | // https://github.com/mseminatore/TeslaJS 5 | // 6 | // Copyright (c) 2016 Mark Seminatore 7 | // 8 | // Refer to included LICENSE file for usage rights and restrictions 9 | //===================================================================== 10 | "use strict"; 11 | 12 | require('colors'); 13 | var program = require('commander'); 14 | var framework = require('./sampleFramework.js'); 15 | 16 | // 17 | // 18 | // 19 | program 20 | .usage('[options]') 21 | .option('-u, --username [string]', 'username (needed only if token not cached)') 22 | .option('-i, --index ', 'vehicle index (first car by default)', parseInt) 23 | .option('-U, --uri [string]', 'URI of test server (e.g. http://127.0.0.1:3000)') 24 | .parse(process.argv); 25 | 26 | // 27 | var sample = new framework.SampleFramework(program, sampleMain); 28 | sample.run(); 29 | 30 | // 31 | // 32 | // 33 | function sampleMain(tjs, options) { 34 | 35 | tjs.remoteStart(options, function (err, result) { 36 | if (err) { 37 | console.log(err); 38 | return; 39 | } 40 | 41 | if (result) { 42 | console.log("\nCommand completed successfully!\n"); 43 | console.log("You may now begin driving.\n"); 44 | console.log("You must start driving within " + "2 minutes".bold.green + " or Remote Start will expire."); 45 | } else { 46 | console.log(result.reason.red); 47 | } 48 | }); 49 | } 50 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": { 3 | "name": "Mark Seminatore", 4 | "url": "https://github.com/mseminatore/TeslaJS" 5 | }, 6 | "bugs": { 7 | "url": "https://github.com/mseminatore/TeslaJS/issues" 8 | }, 9 | "bundleDependencies": [], 10 | "dependencies": { 11 | "promise": "^8.0.3", 12 | "request": "^2.88.2", 13 | "ws": "^8.0.0" 14 | }, 15 | "deprecated": false, 16 | "description": "Full-featured Tesla REST API NodeJS package", 17 | "devDependencies": { 18 | "colors": "^1.4.0", 19 | "commander": "^12.0.0", 20 | "coveralls": "^3.0.11", 21 | "istanbul": "^0.4.5", 22 | "jsdoc-to-markdown": "^8.0.0", 23 | "jshint": "^2.13.0", 24 | "mocha": "^10.0.0", 25 | "sepia": "^2.0.2" 26 | }, 27 | "directories": { 28 | "doc": "docs", 29 | "test": "test" 30 | }, 31 | "homepage": "https://www.teslajs.org", 32 | "keywords": [ 33 | "Tesla", 34 | "Model S", 35 | "Model X", 36 | "Model 3", 37 | "REST" 38 | ], 39 | "license": "MIT", 40 | "main": "teslajs.js", 41 | "name": "teslajs", 42 | "repository": { 43 | "type": "git", 44 | "url": "https://github.com/mseminatore/TeslaJS.git" 45 | }, 46 | "scripts": { 47 | "minify": "uglifyjs teslajs.js -c -m --comments -o teslajs.min.js", 48 | "prepublishOnly": "uglifyjs teslajs.js -c -m --comments -o teslajs.min.js", 49 | "test": "jshint teslajs.js samples && ./node_modules/.bin/istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js --verbose" 50 | }, 51 | "version": "4.10.0" 52 | } 53 | -------------------------------------------------------------------------------- /samples/cancelUpdate.js: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // This sample demonstrates using TeslaJS 3 | // 4 | // https://github.com/mseminatore/TeslaJS 5 | // 6 | // Copyright (c) 2016 Mark Seminatore 7 | // 8 | // Refer to included LICENSE file for usage rights and restrictions 9 | //===================================================================== 10 | "use strict"; 11 | 12 | require('colors'); 13 | var program = require('commander'); 14 | var framework = require('./sampleFramework.js'); 15 | 16 | // 17 | // 18 | // 19 | program 20 | .option('-u, --username [string]', 'username (needed only if token not cached)') 21 | .option('-p, --password [string]', 'password (needed only if token not cached)') 22 | .option('-i, --index ', 'vehicle index (first car by default)', parseInt) 23 | .option('-U, --uri [string]', 'URI of test server (e.g. http://127.0.0.1:3000)') 24 | .parse(process.argv); 25 | 26 | // 27 | var sample = new framework.SampleFramework(program, sampleMain); 28 | sample.run(); 29 | 30 | // 31 | // 32 | // 33 | function sampleMain(tjs, options) { 34 | tjs.cancelSoftwareUpdate(options, function (err, result) { 35 | if (err) { 36 | console.error("\ncancelSoftwareUpdate command: " + "Failed!".red); 37 | } else { 38 | if (result.result) { 39 | console.log("\ncancelSoftwareUpdate command: " + "Succeeded".green); 40 | } else { 41 | console.log("\ncancelSoftwareUpdate command: " + "Failed!".red); 42 | console.log("Reason: " + result.reason.red); 43 | } 44 | } 45 | }); 46 | } 47 | -------------------------------------------------------------------------------- /samples/setTemps.js: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // This sample demonstrates using TeslaJS 3 | // 4 | // https://github.com/mseminatore/TeslaJS 5 | // 6 | // Copyright (c) 2016 Mark Seminatore 7 | // 8 | // Refer to included LICENSE file for usage rights and restrictions 9 | //===================================================================== 10 | "use strict"; 11 | 12 | require('colors'); 13 | var program = require('commander'); 14 | var framework = require('./sampleFramework.js'); 15 | 16 | // 17 | // 18 | // 19 | program 20 | .usage('[options] temperature') 21 | .option('-u, --username [string]', 'username (needed only if token not cached)') 22 | .option('-p, --password [string]', 'password (needed only if token not cached)') 23 | .option('-i, --index ', 'vehicle index (first car by default)', parseInt) 24 | .option('-U, --uri [string]', 'URI of test server (e.g. http://127.0.0.1:3000)') 25 | .parse(process.argv); 26 | 27 | // 28 | var sample = new framework.SampleFramework(program, sampleMain); 29 | sample.run(); 30 | 31 | // 32 | // 33 | // 34 | function f2c(degf) { 35 | return (degf - 32) * 5 / 9; 36 | } 37 | 38 | // 39 | // 40 | // 41 | function sampleMain(tjs, options) { 42 | var temp = program.args[0]; 43 | if (!temp) { 44 | program.help(); 45 | } 46 | 47 | tjs.setTemps(options, f2c(temp), null, function (err, result) { 48 | if (result.result) { 49 | var str = (temp + " Deg.F").green; 50 | console.log("\nTemperature successfully set to: " + str); 51 | } else { 52 | console.log(result.reason.red); 53 | } 54 | }); 55 | } 56 | -------------------------------------------------------------------------------- /samples/simpleStreaming.js: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // This sample demonstrates using TeslaJS 3 | // 4 | // https://github.com/mseminatore/TeslaJS 5 | // 6 | // Copyright (c) 2016 Mark Seminatore 7 | // 8 | // Refer to included LICENSE file for usage rights and restrictions 9 | //===================================================================== 10 | "use strict"; 11 | 12 | require('colors'); 13 | var program = require('commander'); 14 | var framework = require('./sampleFramework.js'); 15 | 16 | // 17 | // 18 | // 19 | program 20 | .usage('[options]') 21 | .option('-i, --index ', 'vehicle index (first car by default)', parseInt) 22 | .option('-U, --uri [string]', 'URI of test server (e.g. http://127.0.0.1:3000)') 23 | .parse(process.argv); 24 | 25 | // 26 | var sample = new framework.SampleFramework(program, sampleMain); 27 | sample.run(); 28 | 29 | // 30 | // 31 | // 32 | function sampleMain(tjs, options) { 33 | 34 | var streamingOptions = { 35 | vehicle_id: options.vehicle_id, 36 | authToken: options.authToken 37 | }; 38 | 39 | console.log("\nNote: " + "Inactive vehicle streaming responses can take up to several minutes.".green); 40 | console.log("\nStreaming starting...".cyan); 41 | 42 | console.log("Columns: timestamp," + tjs.streamingColumns.toString()); 43 | 44 | tjs.startStreaming(streamingOptions, function (error, response, body) { 45 | if (error) { 46 | console.log(error); 47 | return; 48 | } 49 | 50 | // display the streaming results 51 | console.log(body); 52 | 53 | console.log("...Streaming ended.".cyan); 54 | }); 55 | } 56 | -------------------------------------------------------------------------------- /samples/openTrunk.js: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // This sample demonstrates using TeslaJS 3 | // 4 | // https://github.com/mseminatore/TeslaJS 5 | // 6 | // Copyright (c) 2016 Mark Seminatore 7 | // 8 | // Refer to included LICENSE file for usage rights and restrictions 9 | //===================================================================== 10 | "use strict"; 11 | 12 | require('colors'); 13 | var program = require('commander'); 14 | var framework = require('./sampleFramework.js'); 15 | 16 | // 17 | // 18 | // 19 | program 20 | .usage('[options] trunk|frunk') 21 | .option('-u, --username [string]', 'username (needed only if token not cached)') 22 | .option('-p, --password [string]', 'password (needed only if token not cached)') 23 | .option('-i, --index ', 'vehicle index (first car by default)', parseInt) 24 | .option('-U, --uri [string]', 'URI of test server (e.g. http://127.0.0.1:3000)') 25 | .parse(process.argv); 26 | 27 | // 28 | var sample = new framework.SampleFramework(program, sampleMain); 29 | sample.run(); 30 | 31 | // 32 | // 33 | // 34 | function sampleMain(tjs, options) { 35 | var which = program.args[0]; 36 | 37 | if (!which) { 38 | program.help(); 39 | } 40 | 41 | if (which.toUpperCase() == "FRUNK") { 42 | which = tjs.FRUNK; 43 | } else { 44 | which = tjs.TRUNK; 45 | } 46 | 47 | tjs.openTrunk(options, which, function (err, response) { 48 | if (response.result) { 49 | var str = which.toUpperCase(); 50 | console.log("\n" + str.bgGreen + " actuated."); 51 | } 52 | else { 53 | console.error(response.reason.red); 54 | } 55 | }); 56 | } 57 | -------------------------------------------------------------------------------- /samples/calendar.js: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // This sample demonstrates using TeslaJS 3 | // 4 | // https://github.com/mseminatore/TeslaJS 5 | // 6 | // Copyright (c) 2016 Mark Seminatore 7 | // 8 | // Refer to included LICENSE file for usage rights and restrictions 9 | //===================================================================== 10 | "use strict"; 11 | 12 | require('colors'); 13 | var program = require('commander'); 14 | var framework = require('./sampleFramework.js'); 15 | 16 | // 17 | // 18 | // 19 | program 20 | .option('-u, --username [string]', 'username (needed only if token not cached)') 21 | .option('-p, --password [string]', 'password (needed only if token not cached)') 22 | .option('-i, --index ', 'vehicle index (first car by default)', parseInt) 23 | .option('-n, --name [string]', 'phone name') 24 | .option('-U, --uri [string]', 'URI of test server (e.g. http://127.0.0.1:3000)') 25 | .parse(process.argv); 26 | 27 | // 28 | var sample = new framework.SampleFramework(program, sampleMain); 29 | sample.run(); 30 | 31 | // 32 | // 33 | // 34 | function sampleMain(tjs, options) { 35 | var entry = tjs.makeCalendarEntry( 36 | "Event name", 37 | "Home", 38 | new Date(2016, 4, 5, 12, 0).getTime(), 39 | new Date(2016, 4, 5, 1, 0).getTime(), 40 | "you@gmail.com", 41 | "Phone Bluetooth name" 42 | ); 43 | 44 | console.log(JSON.stringify(entry)); 45 | 46 | tjs.calendar(options, entry, function (err, result) { 47 | if (result.result) { 48 | console.log("\nCalendar updated! ".bold.green); 49 | } else { 50 | console.log(result.reason.red); 51 | } 52 | }); 53 | } 54 | -------------------------------------------------------------------------------- /samples/odometer.js: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // This sample demonstrates using TeslaJS 3 | // 4 | // https://github.com/mseminatore/TeslaJS 5 | // 6 | // Copyright (c) 2016 Mark Seminatore 7 | // 8 | // Refer to included LICENSE file for usage rights and restrictions 9 | //===================================================================== 10 | "use strict"; 11 | 12 | require('colors'); 13 | var program = require('commander'); 14 | var framework = require('./sampleFramework.js'); 15 | 16 | // 17 | // 18 | // 19 | program 20 | .option('-u, --username [string]', 'username (needed only if token not cached)') 21 | .option('-p, --password [string]', 'password (needed only if token not cached)') 22 | .option('-U, --uri [string]', 'URI of test server (e.g. http://127.0.0.1:3000)') 23 | .parse(process.argv); 24 | 25 | // 26 | var sample = new framework.SampleFramework(program, sampleMain); 27 | sample.run(); 28 | 29 | // 30 | // 31 | // 32 | function addCommas(str) 33 | { 34 | str += ''; 35 | var x = str.split('.'); 36 | var x1 = x[0]; 37 | var x2 = x.length > 1 ? '.' + x[1] : ''; 38 | var rgx = /(\d+)(\d{3})/; 39 | 40 | while (rgx.test(x1)) { 41 | x1 = x1.replace(rgx, '$1' + ',' + '$2'); 42 | } 43 | 44 | return x1 + x2; 45 | } 46 | 47 | // 48 | // 49 | // 50 | function sampleMain(tjs, options) { 51 | tjs.vehicleState(options, function (err, vehicle_state) { 52 | console.log("\nOdometer"); 53 | console.log("--------"); 54 | 55 | var miles = addCommas(Math.round(vehicle_state.odometer).toString()); 56 | console.log(miles.green + " mi"); 57 | 58 | var km = addCommas(Math.round(vehicle_state.odometer * 1.609344).toString()); 59 | console.log(km.green + " km"); 60 | }); 61 | } 62 | -------------------------------------------------------------------------------- /samples/valet.js: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // This sample demonstrates using TeslaJS 3 | // 4 | // https://github.com/mseminatore/TeslaJS 5 | // 6 | // Copyright (c) 2016 Mark Seminatore 7 | // 8 | // Refer to included LICENSE file for usage rights and restrictions 9 | //===================================================================== 10 | "use strict"; 11 | 12 | require('colors'); 13 | var program = require('commander'); 14 | var framework = require('./sampleFramework.js'); 15 | 16 | // 17 | // 18 | // 19 | program 20 | .usage('[options] ON|OFF pin') 21 | .option('-u, --username [string]', 'username (needed only if token not cached)') 22 | .option('-p, --password [string]', 'password (needed only if token not cached)') 23 | .option('-i, --index ', 'vehicle index (first car by default)', parseInt) 24 | .option('-U, --uri [string]', 'URI of test server (e.g. http://127.0.0.1:3000)') 25 | .parse(process.argv); 26 | 27 | // 28 | var sample = new framework.SampleFramework(program, sampleMain); 29 | sample.run(); 30 | 31 | // 32 | // 33 | // 34 | function sampleMain(tjs, options) { 35 | var mode = program.args[0]; 36 | var pin = program.args[1]; 37 | 38 | if (!mode || !pin) { 39 | program.help(); 40 | } 41 | 42 | if (mode.toUpperCase() == "ON") { 43 | mode = true; 44 | } else { 45 | mode = false; 46 | } 47 | 48 | tjs.setValetMode(options, mode, pin, function (err, response) { 49 | if (response.result) { 50 | var str = mode ? "ENABLED" : "DISABLED"; 51 | console.log("\nValet mode: " + str.bgGreen); 52 | } 53 | else { 54 | console.error(response.reason.red); 55 | } 56 | }); 57 | } 58 | -------------------------------------------------------------------------------- /samples/sunroof.js: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // This sample demonstrates using TeslaJS 3 | // 4 | // https://github.com/mseminatore/TeslaJS 5 | // 6 | // Copyright (c) 2016 Mark Seminatore 7 | // 8 | // Refer to included LICENSE file for usage rights and restrictions 9 | //===================================================================== 10 | "use strict"; 11 | 12 | require('colors'); 13 | var program = require('commander'); 14 | var framework = require('./sampleFramework.js'); 15 | 16 | // 17 | // 18 | // 19 | program 20 | .usage('[options] close|vent') 21 | .option('-u, --username [string]', 'username (needed only if token not cached)') 22 | .option('-p, --password [string]', 'password (needed only if token not cached)') 23 | .option('-i, --index ', 'vehicle index (first car by default)', parseInt) 24 | .option('-U, --uri [string]', 'URI of test server (e.g. http://127.0.0.1:3000)') 25 | .parse(process.argv); 26 | 27 | // 28 | var sample = new framework.SampleFramework(program, sampleMain); 29 | sample.run(); 30 | 31 | // 32 | // 33 | // 34 | function sampleMain(tjs, options) { 35 | var state = program.args[0]; 36 | 37 | if (!state) { 38 | program.help(); 39 | } 40 | 41 | if (state.toLowerCase() == "closed") { 42 | state = "close"; 43 | } 44 | 45 | if (state.toLowerCase() != "close" && state.toLowerCase() != "vent") { 46 | program.help(); 47 | } 48 | 49 | tjs.sunRoofControl(options, state, function (err, result) { 50 | if (result && result.result) { 51 | console.log("\nSunroof successfully moved to : " + state.bgGreen); 52 | } else { 53 | console.log(err); 54 | console.log("Invalid option".red); 55 | } 56 | }); 57 | } 58 | -------------------------------------------------------------------------------- /samples/scheduleUpdate.js: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // This sample demonstrates using TeslaJS 3 | // 4 | // https://github.com/mseminatore/TeslaJS 5 | // 6 | // Copyright (c) 2016 Mark Seminatore 7 | // 8 | // Refer to included LICENSE file for usage rights and restrictions 9 | //===================================================================== 10 | "use strict"; 11 | 12 | require('colors'); 13 | var program = require('commander'); 14 | var framework = require('./sampleFramework.js'); 15 | 16 | // 17 | // 18 | // 19 | program 20 | .usage('[options] delay') 21 | .option('-u, --username [string]', 'username (needed only if token not cached)') 22 | .option('-p, --password [string]', 'password (needed only if token not cached)') 23 | .option('-i, --index ', 'vehicle index (first car by default)', parseInt) 24 | .option('-U, --uri [string]', 'URI of test server (e.g. http://127.0.0.1:3000)') 25 | .parse(process.argv); 26 | 27 | // 28 | var sample = new framework.SampleFramework(program, sampleMain); 29 | sample.run(); 30 | 31 | // 32 | // 33 | // 34 | function sampleMain(tjs, options) { 35 | var offset = program.args[0]; 36 | if (!offset) { 37 | program.help(); 38 | } 39 | 40 | tjs.scheduleSoftwareUpdate(options, offset, function (err, result) { 41 | if (err) { 42 | console.error("\nscheduleSoftwareUpdate command: " + "Failed!".red); 43 | } else { 44 | if (result.result) { 45 | console.log("\nscheduleSoftwareUpdate command: " + "Succeeded".green); 46 | } else { 47 | console.log("\nscheduleSoftwareUpdate command: " + "Failed!".red); 48 | console.log("Reason: " + result.reason.red); 49 | } 50 | } 51 | }); 52 | } 53 | -------------------------------------------------------------------------------- /samples/setChargeLimit.js: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // This sample demonstrates using TeslaJS 3 | // 4 | // https://github.com/mseminatore/TeslaJS 5 | // 6 | // Copyright (c) 2016 Mark Seminatore 7 | // 8 | // Refer to included LICENSE file for usage rights and restrictions 9 | //===================================================================== 10 | "use strict"; 11 | 12 | require('colors'); 13 | var program = require('commander'); 14 | var framework = require('./sampleFramework.js'); 15 | 16 | // 17 | // 18 | // 19 | program 20 | .usage('[options] number|standard|storage|range') 21 | .option('-u, --username [string]', 'username (needed only if token not cached)') 22 | .option('-p, --password [string]', 'password (needed only if token not cached)') 23 | .option('-i, --index ', 'vehicle index (first car by default)', parseInt) 24 | .option('-U, --uri [string]', 'URI of test server (e.g. http://127.0.0.1:3000)') 25 | .parse(process.argv); 26 | 27 | // 28 | var sample = new framework.SampleFramework(program, sampleMain); 29 | sample.run(); 30 | 31 | // 32 | // 33 | // 34 | function sampleMain(tjs, options) { 35 | var amt = program.args[0]; 36 | if (!amt) { 37 | program.help(); 38 | } 39 | 40 | // handle named values 41 | if (amt.toLowerCase() == "standard") { 42 | amt = 90; 43 | } else if (amt.toLowerCase() == "range") { 44 | amt = 100; 45 | } else if (amt.toLowerCase() == "storage") { 46 | amt = 50; 47 | } 48 | 49 | tjs.setChargeLimit(options, amt, function (err, result) { 50 | if (result.result) { 51 | var str = (amt + "%").green; 52 | console.log("\nCharge limit successfully set to: " + str); 53 | } else { 54 | console.log(result.reason); 55 | } 56 | }); 57 | } 58 | 59 | -------------------------------------------------------------------------------- /samples/guiSettings.js: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // This sample demonstrates using TeslaJS 3 | // 4 | // https://github.com/mseminatore/TeslaJS 5 | // 6 | // Copyright (c) 2016 Mark Seminatore 7 | // 8 | // Refer to included LICENSE file for usage rights and restrictions 9 | //===================================================================== 10 | "use strict"; 11 | 12 | require('colors'); 13 | var program = require('commander'); 14 | var framework = require('./sampleFramework.js'); 15 | 16 | // 17 | // 18 | // 19 | program 20 | .option('-u, --username [string]', 'username (needed only if token not cached)') 21 | .option('-p, --password [string]', 'password (needed only if token not cached)') 22 | .option('-i, --index ', 'vehicle index (first car by default)', parseInt) 23 | .option('-U, --uri [string]', 'URI of test server (e.g. http://127.0.0.1:3000)') 24 | .parse(process.argv); 25 | 26 | // 27 | var sample = new framework.SampleFramework(program, sampleMain); 28 | sample.run(); 29 | 30 | // 31 | // 32 | // 33 | function sampleMain(tjs, options) { 34 | tjs.guiSettings(options, function (err, guiSettings) { 35 | if (!guiSettings) { 36 | console.error("\nError: " + "No response to guiSettings() query!".red); 37 | return; 38 | } 39 | 40 | console.log("\ngui_distance_units: " + guiSettings.gui_distance_units.green); 41 | console.log("gui_temperature_units: " + guiSettings.gui_temperature_units.green); 42 | console.log("gui_charge_rate_units: " + guiSettings.gui_charge_rate_units.green); 43 | 44 | var timeFormat = guiSettings.gui_24_hour_time ? "YES".green : "NO".green; 45 | console.log("gui_24_hour_time: " + timeFormat); 46 | console.log("gui_range_display: " + guiSettings.gui_range_display.green); 47 | }); 48 | } 49 | -------------------------------------------------------------------------------- /samples/login.js: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // This sample demonstrates using TeslaJS 3 | // 4 | // https://github.com/mseminatore/TeslaJS 5 | // 6 | // Copyright (c) 2016 Mark Seminatore 7 | // 8 | // Refer to included LICENSE file for usage rights and restrictions 9 | //===================================================================== 10 | "use strict"; 11 | 12 | var tjs = require('../teslajs'); 13 | var fs = require('fs'); 14 | require('colors'); 15 | var program = require('commander'); 16 | 17 | program 18 | .usage('[options] username password [MFA code] [MFA device name]') 19 | .option('-U, --uri [string]', 'URI of test server (e.g. http://127.0.0.1:3000)') 20 | .parse(process.argv); 21 | 22 | if (program.args.length < 2) { 23 | program.help(); 24 | } 25 | 26 | var username = program.args[0]; 27 | var password = program.args[1]; 28 | var mfaPassCode = program.args[2]; 29 | var mfaDeviceName = program.args[3]; 30 | 31 | if (program.uri) { 32 | console.log("Setting portal URI to: " + program.uri); 33 | tjs.setPortalBaseURI(program.uri); 34 | } 35 | 36 | tjs.loginAsync({ 37 | username: username, 38 | password: password, 39 | mfaPassCode: mfaPassCode, 40 | mfaDeviceName: mfaDeviceName 41 | }).done( 42 | // success! 43 | function (result) { 44 | if (!result.authToken) { 45 | console.error("Login failed!".red); 46 | process.exit(1); 47 | } 48 | 49 | var token = JSON.stringify(result.body); 50 | 51 | if (token) { 52 | console.log("Login " + "Successfull.".green); 53 | // console.log("OAuth token is: " + token.green); 54 | 55 | fs.writeFileSync('.token', token, 'utf8'); 56 | console.log('Auth token saved!'); 57 | } 58 | }, 59 | // failure! 60 | function (error) { 61 | console.error(error); 62 | } 63 | ); 64 | -------------------------------------------------------------------------------- /samples/navRequest.js: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // This sample demonstrates using TeslaJS 3 | // 4 | // https://github.com/mseminatore/TeslaJS 5 | // 6 | // Copyright (c) 2016 Mark Seminatore 7 | // 8 | // Refer to included LICENSE file for usage rights and restrictions 9 | //===================================================================== 10 | "use strict"; 11 | 12 | require('colors'); 13 | var program = require('commander'); 14 | var framework = require('./sampleFramework.js'); 15 | 16 | // 17 | // 18 | // 19 | program 20 | .usage('[options] subject text [locale]') 21 | .option('-u, --username [string]', 'username (needed only if token not cached)') 22 | .option('-p, --password [string]', 'password (needed only if token not cached)') 23 | .option('-i, --index ', 'vehicle index (first car by default)', parseInt) 24 | .option('-U, --uri [string]', 'URI of test server (e.g. http://127.0.0.1:3000)') 25 | .parse(process.argv); 26 | 27 | // 28 | var sample = new framework.SampleFramework(program, sampleMain); 29 | sample.run(); 30 | 31 | // 32 | // 33 | // 34 | function sampleMain(tjs, options) { 35 | var subject = program.args[0]; 36 | var text = program.args[1]; 37 | var locale = program.args[1] || "en-US"; 38 | 39 | if (!subject || !text) { 40 | console.log("\n"); 41 | program.help(); 42 | } 43 | 44 | tjs.navigationRequest(options, subject, text, locale, function (err, result) { 45 | if (err) { 46 | console.error("\nnavigationRequest command: " + "Failed!".red + "\n"); 47 | } else { 48 | if (result.result) { 49 | console.log("\nnavigationRequest command: " + "Succeeded".green + "\n"); 50 | } else { 51 | console.log("\nnavigationRequest command: " + "Failed!".red + "\n"); 52 | console.log("Reason: " + result.reason.red + "\n"); 53 | } 54 | } 55 | }); 56 | } 57 | -------------------------------------------------------------------------------- /samples/homelink.js: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // This sample demonstrates using TeslaJS 3 | // 4 | // https://github.com/mseminatore/TeslaJS 5 | // 6 | // Copyright (c) 2016 Mark Seminatore 7 | // 8 | // Refer to included LICENSE file for usage rights and restrictions 9 | //===================================================================== 10 | "use strict"; 11 | 12 | require('colors'); 13 | var program = require('commander'); 14 | var framework = require('./sampleFramework.js'); 15 | 16 | // 17 | // 18 | // 19 | program 20 | .option('-u, --username [string]', 'username (needed only if token not cached)') 21 | .option('-p, --password [string]', 'password (needed only if token not cached)') 22 | .option('-i, --index ', 'vehicle index (first car by default)', parseInt) 23 | .option('-U, --uri [string]', 'URI of test server (e.g. http://127.0.0.1:3000)') 24 | .parse(process.argv); 25 | 26 | // 27 | var sample = new framework.SampleFramework(program, sampleMain); 28 | sample.run(); 29 | 30 | // 31 | // 32 | // 33 | function sampleMain(tjs, options) { 34 | tjs.vehicleData(options, function (err, data) { 35 | if (data.drive_state) { 36 | var latitude = data.drive_state.latitude || 0; 37 | var longitude = data.drive_state.longitude || 0; 38 | 39 | console.log("\nHomelink devices: " + data.vehicle_state.homelink_device_count); 40 | console.log("Homelink nearby: " + data.vehicle_state.homelink_nearby); 41 | 42 | tjs.homelink(options, latitude, longitude, function (err, result) { 43 | if (result.result) { 44 | console.log("\nHomelink: " + "Door signaled!".bold.green); 45 | } else { 46 | console.log("\nHomelink: " + result.reason.red); 47 | } 48 | }); 49 | } 50 | else { 51 | console.log("Drive State: " + data.drive_state.reason.red); 52 | } 53 | }); 54 | } 55 | -------------------------------------------------------------------------------- /samples/vehicleConfig.js: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // This sample demonstrates using TeslaJS 3 | // 4 | // https://github.com/mseminatore/TeslaJS 5 | // 6 | // Copyright (c) 2016 Mark Seminatore 7 | // 8 | // Refer to included LICENSE file for usage rights and restrictions 9 | //===================================================================== 10 | "use strict"; 11 | 12 | require('colors'); 13 | var program = require('commander'); 14 | var framework = require('./sampleFramework.js'); 15 | 16 | // 17 | // 18 | // 19 | program 20 | .option('-u, --username [string]', 'username (needed only if token not cached)') 21 | .option('-p, --password [string]', 'password (needed only if token not cached)') 22 | .option('-i, --index ', 'vehicle index (first car by default)', parseInt) 23 | .option('-U, --uri [string]', 'URI of test server (e.g. http://127.0.0.1:3000)') 24 | .parse(process.argv); 25 | 26 | // 27 | var sample = new framework.SampleFramework(program, sampleMain); 28 | sample.run(); 29 | 30 | // 31 | // 32 | // 33 | function sampleMain(tjs, options) { 34 | tjs.vehicleConfigAsync(options).then( function (vehicle_config) { 35 | console.log("\nCar type: " + vehicle_config.car_type.toUpperCase().green); 36 | console.log("Exterior color: " + vehicle_config.exterior_color.green); 37 | if (vehicle_config.eu_vehicle) { 38 | console.log("EU vehicle: " + "Yes".bgGreen); 39 | } 40 | 41 | console.log("Ludicrous mode: " + (vehicle_config.has_ludicrous_mode ? "YES".bgGreen : "No".green)); 42 | console.log("Sunroof installed: " + (vehicle_config.sun_roof_installed ? "YES".bgGreen : "No".green)); 43 | console.log("Motorized charge port: " + (vehicle_config.motorized_charge_port ? "YES".bgGreen : "No".green)); 44 | console.log("Spoiler type: " + vehicle_config.spoiler_type.green); 45 | console.log("Trim badging: " + vehicle_config.trim_badging.toUpperCase().green); 46 | console.log("Wheel type: " + vehicle_config.wheel_type.green + "\n"); 47 | }); 48 | } 49 | -------------------------------------------------------------------------------- /samples/climate.js: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // This sample demonstrates using TeslaJS 3 | // 4 | // https://github.com/mseminatore/TeslaJS 5 | // 6 | // Copyright (c) 2016 Mark Seminatore 7 | // 8 | // Refer to included LICENSE file for usage rights and restrictions 9 | //===================================================================== 10 | "use strict"; 11 | 12 | require('colors'); 13 | var program = require('commander'); 14 | var framework = require('./sampleFramework.js'); 15 | 16 | // 17 | // 18 | // 19 | program 20 | .option('-u, --username [string]', 'username (needed only if token not cached)') 21 | .option('-p, --password [string]', 'password (needed only if token not cached)') 22 | .option('-i, --index ', 'vehicle index (first car by default)', parseInt) 23 | .option('-U, --uri [string]', 'URI of test server (e.g. http://127.0.0.1:3000)') 24 | .parse(process.argv); 25 | 26 | // 27 | var sample = new framework.SampleFramework(program, sampleMain); 28 | sample.run(); 29 | 30 | function ctof(degc) { 31 | return Math.round(degc * 9 / 5 + 32); 32 | } 33 | 34 | // 35 | // 36 | // 37 | function sampleMain(tjs, options) { 38 | tjs.climateState(options, function (err, climate_state) { 39 | var str = climate_state.is_auto_conditioning_on ? "ON".red : "OFF".green; 40 | console.log("\nClimate is currently: " + str); 41 | 42 | if (climate_state.fan_status) { 43 | console.log("Fan Speed: " + climate_state.fan_status.toString().green); 44 | } 45 | 46 | if (climate_state.inside_temp && climate_state.inside_temp !== 0) { 47 | console.log("\nInterior: " + ctof(climate_state.inside_temp).toString().green + " Deg.F"); 48 | } 49 | 50 | if (climate_state.outside_temp && climate_state.outside_temp !== 0) { 51 | console.log("Exterior: " + ctof(climate_state.outside_temp).toString().green + " Deg.F"); 52 | } 53 | 54 | console.log("\nDriver setting: " + ctof(climate_state.driver_temp_setting).toString().green + " Deg.F"); 55 | console.log("Passenger setting: " + ctof(climate_state.passenger_temp_setting).toString().green + " Deg.F\n"); 56 | 57 | str = climate_state.is_front_defroster_on ? "ON".red : "OFF".green; 58 | console.log("Front defroster: " + str) 59 | 60 | str = climate_state.is_rear_defroster_on ? "ON".red : "OFF".green; 61 | console.log("Rear defroster: " + str + "\n") 62 | }); 63 | } 64 | -------------------------------------------------------------------------------- /samples/media.js: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // This sample demonstrates using TeslaJS 3 | // 4 | // https://github.com/mseminatore/TeslaJS 5 | // 6 | // Copyright (c) 2016 Mark Seminatore 7 | // 8 | // Refer to included LICENSE file for usage rights and restrictions 9 | //===================================================================== 10 | "use strict"; 11 | 12 | require('colors'); 13 | var program = require('commander'); 14 | var framework = require('./sampleFramework.js'); 15 | 16 | // 17 | // 18 | // 19 | program 20 | .usage('[options] [toggle | next | prev | next_fav | prev_fav | up | down]') 21 | .option('-u, --username [string]', 'username (needed only if token not cached)') 22 | .option('-p, --password [string]', 'password (needed only if token not cached)') 23 | .option('-i, --index ', 'vehicle index (first car by default)', parseInt) 24 | .option('-U, --uri [string]', 'URI of test server (e.g. http://127.0.0.1:3000)') 25 | .parse(process.argv); 26 | 27 | // 28 | var sample = new framework.SampleFramework(program, sampleMain); 29 | sample.run(); 30 | 31 | // 32 | // 33 | // 34 | function cb(err, result) { 35 | if (err) { 36 | console.error("\nCommand: " + "Failed!".red); 37 | } else { 38 | if (result.result) { 39 | console.log("\nCommand: " + "Succeeded".green); 40 | } else { 41 | console.log("\nCommand: " + "Failed!".red); 42 | console.log("Reason: " + result.reason.red); 43 | } 44 | } 45 | } 46 | 47 | // 48 | // 49 | // 50 | function sampleMain(tjs, options) { 51 | var cmd = program.args[0]; 52 | 53 | if (!cmd) { 54 | console.log("\n"); 55 | program.help(); 56 | } 57 | 58 | switch(cmd) { 59 | case "toggle": 60 | tjs.mediaTogglePlayback(options, cb); 61 | break; 62 | 63 | case "next": 64 | tjs.mediaPlayNext(options, cb); 65 | break; 66 | 67 | case "prev": 68 | tjs.mediaPlayPrevious(options, cb); 69 | break; 70 | 71 | case "next_fav": 72 | tjs.mediaPlayNextFavorite(options, cb); 73 | break; 74 | 75 | case "prev_fav": 76 | tjs.mediaPlayPreviousFavorite(options, cb); 77 | break; 78 | 79 | case "up": 80 | tjs.mediaVolumeUp(options, cb); 81 | break; 82 | 83 | case "down": 84 | tjs.mediaVolumeDown(options, cb); 85 | break; 86 | 87 | default: 88 | console.error("\nUnrecognized command [" + cmd.yellow + "]: " + "Failed!".red); 89 | 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ master ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ master ] 20 | schedule: 21 | - cron: '44 6 * * 2' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'javascript' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] 37 | # Learn more: 38 | # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed 39 | 40 | steps: 41 | - name: Checkout repository 42 | uses: actions/checkout@v2 43 | 44 | # Initializes the CodeQL tools for scanning. 45 | - name: Initialize CodeQL 46 | uses: github/codeql-action/init@v2 47 | with: 48 | languages: ${{ matrix.language }} 49 | # If you wish to specify custom queries, you can do so here or in a config file. 50 | # By default, queries listed here will override any specified in a config file. 51 | # Prefix the list here with "+" to use these queries and those in the config file. 52 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 53 | 54 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 55 | # If this step fails, then you should remove it and run the build manually (see below) 56 | - name: Autobuild 57 | uses: github/codeql-action/autobuild@v2 58 | 59 | # ℹ️ Command-line programs to run using the OS shell. 60 | # 📚 https://git.io/JvXDl 61 | 62 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 63 | # and modify them (or add more) to build your code if your project 64 | # uses a compiled language 65 | 66 | #- run: | 67 | # make bootstrap 68 | # make release 69 | 70 | - name: Perform CodeQL Analysis 71 | uses: github/codeql-action/analyze@v2 72 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at support@teslajs.org. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /samples/geoloc.js: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // This sample demonstrates using TeslaJS 3 | // 4 | // https://github.com/mseminatore/TeslaJS 5 | // 6 | // Copyright (c) 2016 Mark Seminatore 7 | // 8 | // Refer to included LICENSE file for usage rights and restrictions 9 | //===================================================================== 10 | "use strict"; 11 | 12 | var request = require('request'); 13 | require('colors'); 14 | var program = require('commander'); 15 | var framework = require('./sampleFramework.js'); 16 | 17 | // 18 | // 19 | // 20 | program 21 | .option('-u, --username [string]', 'username (needed only if token not cached)') 22 | .option('-p, --password [string]', 'password (needed only if token not cached)') 23 | .option('-g, --geocode', 'geocode the street address') 24 | .option('-i, --index ', 'vehicle index (first car by default)', parseInt) 25 | .option('-U, --uri [string]', 'URI of test server (e.g. http://127.0.0.1:3000)') 26 | .parse(process.argv); 27 | 28 | // 29 | var sample = new framework.SampleFramework(program, sampleMain); 30 | sample.run(); 31 | 32 | // 33 | // Turn compass heading into friendly heading (NSEW, etc.) 34 | // 35 | function compassDirs(heading) { 36 | if (heading > 337 || heading < 23) { 37 | return "North"; 38 | } 39 | 40 | if (heading < 67) { 41 | return "North East"; 42 | } 43 | 44 | if (heading < 112) { 45 | return "East"; 46 | } 47 | 48 | if (heading < 157) { 49 | return "South East"; 50 | } 51 | 52 | if (heading < 202) { 53 | return "South"; 54 | } 55 | 56 | if (heading < 247) { 57 | return "South West"; 58 | } 59 | 60 | if (heading < 292) { 61 | return "West"; 62 | } 63 | 64 | if (heading < 337) { 65 | return "North West"; 66 | } 67 | 68 | return heading; 69 | } 70 | 71 | // 72 | // 73 | // 74 | function sampleMain(tjs, options) { 75 | tjs.driveState(options, function (err, drive_state) { 76 | if (drive_state) { 77 | 78 | var state = drive_state.shift_state || "Parked"; 79 | console.log("\nState: " + state.green); 80 | 81 | if (drive_state.speed) { 82 | var str = drive_state.speed || 0; 83 | console.log("Speed: " + str.green); 84 | } 85 | 86 | console.log("Heading: " + compassDirs(drive_state.heading).green); 87 | 88 | var latitude = drive_state.latitude || 0; 89 | var longitude = drive_state.longitude || 0; 90 | 91 | console.log("GPS: " + latitude.toString().green + ", " + longitude.toString().green); 92 | 93 | if (program.geocode) { 94 | request({ 95 | method: 'GET', 96 | url: "http://api.geonames.org/findNearestAddressJSON?lat=" + latitude + "&lng=" + longitude + "&username=demo", 97 | headers: { 'Content-Type': 'application/json; charset=utf-8' } 98 | }, function (error, response, body) { 99 | var res = JSON.parse(body).address; 100 | 101 | console.log('\nClosest resolved address'); 102 | console.log('------------------------'); 103 | console.log(res.streetNumber + " " + res.street); 104 | console.log(res.placename + ", " + res.adminCode1 + " " + res.postalcode + " " + res.countryCode); 105 | }); 106 | } 107 | console.log(""); 108 | } 109 | else { 110 | console.log(drive_state.reason.red); 111 | } 112 | }); 113 | } 114 | -------------------------------------------------------------------------------- /samples/sampleFramework.js: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // This sample framework is used to demonstrate using TeslaJS 3 | // 4 | // https://github.com/mseminatore/TeslaJS 5 | // 6 | // Copyright (c) 2016 Mark Seminatore 7 | // 8 | // Refer to included LICENSE file for usage rights and restrictions 9 | //===================================================================== 10 | "use strict"; 11 | 12 | var fs = require('fs'); 13 | var tjs = require('../teslajs'); 14 | require('colors'); 15 | 16 | function logo() { 17 | console.log("\n"); 18 | console.log("TTTTT EEEEE SSSSS L AAAAA J SSSSS"); 19 | console.log(" T EEEEE S L AAAAA J S"); 20 | console.log(" TTT s L J S"); 21 | console.log(" T EEEEE SSSSS L AAAAA J SSSSS"); 22 | console.log(" T S L A A J S"); 23 | console.log(" T EEEEE S L A A J J S"); 24 | console.log(" T EEEEE SSSSS LLLLL A A JJJJJ SSSSS"); 25 | console.log("========================================="); 26 | } 27 | 28 | exports.SampleFramework = function SampleFramework(program, main) { 29 | this.program = program; 30 | this.tokenFound = false; 31 | this.main = main; 32 | 33 | this.login_cb = function (err, result) { 34 | if (result.error) { 35 | console.error("Login failed!".red); 36 | console.warn(JSON.stringify(result.error)); 37 | return; 38 | } 39 | 40 | logo(); 41 | 42 | var options = { authToken: result.authToken }; 43 | tjs.vehicles(options, function (err, vehicles) { 44 | if (err) { 45 | console.log("\nError: " + err.red); 46 | return; 47 | } 48 | 49 | var vehicle = vehicles[program.index || 0]; 50 | options.vehicleID = vehicle.id_s; 51 | options.vehicle_id = vehicle.vehicle_id; 52 | options.tokens = vehicle.tokens; 53 | 54 | if (vehicle.state.toUpperCase() == "OFFLINE") { 55 | console.log("\nResult: " + "Unable to contact vehicle, exiting!".bold.red); 56 | return; 57 | } 58 | 59 | var carType = tjs.getModel(vehicle); 60 | 61 | console.log("\nVehicle " + vehicle.vin.green + " - " + carType.green + " ( '" + vehicle.display_name.cyan + "' ) is: " + vehicle.state.toUpperCase().bold.green); 62 | 63 | if (main) { 64 | main(tjs, options); 65 | } 66 | }); 67 | } 68 | 69 | this.run = function () { 70 | try { 71 | this.tokenFound = fs.statSync('.token').isFile(); 72 | } catch (e) { 73 | } 74 | 75 | if (program.uri) { 76 | console.log("Setting portal URI to: " + program.uri); 77 | tjs.setPortalBaseURI(program.uri); 78 | } 79 | 80 | if (this.tokenFound) { 81 | var fileStr = fs.readFileSync('.token', 'utf8'); 82 | var token = JSON.parse(fileStr); 83 | 84 | if (!token) { 85 | program.help(); 86 | } 87 | 88 | if (token.access_token) { 89 | token = token.access_token; 90 | } 91 | 92 | this.login_cb(null, { error: false, authToken: token }); 93 | } else { 94 | var username = program.username || process.env.TESLAJS_USER; 95 | var password = program.password || process.env.TESLAJS_PASS; 96 | 97 | if (!username || !password) { 98 | program.help(); 99 | } 100 | 101 | tjs.login(username, password, this.login_cb); 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /samples/vehicle.js: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // This sample demonstrates using TeslaJS 3 | // 4 | // https://github.com/mseminatore/TeslaJS 5 | // 6 | // Copyright (c) 2016 Mark Seminatore 7 | // 8 | // Refer to included LICENSE file for usage rights and restrictions 9 | //===================================================================== 10 | "use strict"; 11 | 12 | require('colors'); 13 | var program = require('commander'); 14 | var framework = require('./sampleFramework.js'); 15 | 16 | // 17 | // 18 | // 19 | program 20 | .option('-u, --username [string]', 'username (needed only if token not cached)') 21 | .option('-p, --password [string]', 'password (needed only if token not cached)') 22 | .option('-i, --index ', 'vehicle index (first car by default)', parseInt) 23 | .option('-U, --uri [string]', 'URI of test server (e.g. http://127.0.0.1:3000)') 24 | .parse(process.argv); 25 | 26 | // 27 | var sample = new framework.SampleFramework(program, sampleMain); 28 | sample.run(); 29 | 30 | function milesToKms(miles){ 31 | return miles * 1.609344; 32 | } 33 | 34 | // 35 | // 36 | // 37 | function sampleMain(tjs, options) { 38 | tjs.vehicleDataAsync(options).then( function(vehicleData) { 39 | var vehicle_state = vehicleData.vehicle_state; 40 | var charge_state = vehicleData.charge_state; 41 | 42 | var eu_vehicle = vehicleData.vehicle_config.eu_vehicle; 43 | var unitsInKms = vehicleData.gui_settings.gui_distance_units === "km/hr"; 44 | 45 | var str = vehicle_state.locked ? "LOCKED".bgGreen : "UNLOCKED".yellow; 46 | 47 | console.log("\nCharging state: " + charge_state.charging_state.green); 48 | console.log("Battery level: " + charge_state.battery_level.toString().green + ' / '.green + charge_state.charge_limit_soc.toString().green + ' %'.green); 49 | 50 | console.log("\nRated range: " + (unitsInKms ? Math.round(milesToKms(charge_state.battery_range)).toString().green + ' km' : Math.round(charge_state.battery_range).toString().green + ' mi')); 51 | console.log((eu_vehicle?"Typical":"Ideal")+" range: " + (unitsInKms ? Math.round(milesToKms(charge_state.ideal_battery_range)).toString().green + ' km' : Math.round(charge_state.ideal_battery_range).toString().green + ' mi')); 52 | console.log("Projected range: " + (unitsInKms ? Math.round(milesToKms(charge_state.est_battery_range)).toString().green + ' km' : Math.round(charge_state.est_battery_range).toString().green + ' mi')); 53 | 54 | console.log("\nDoors: " + str); 55 | if (vehicle_state.df) { 56 | console.log("Driver door: " + "OPEN".red); 57 | } 58 | if (vehicle_state.pf) { 59 | console.log("Passenger door: " + "OPEN".red); 60 | } 61 | if (vehicle_state.dr) { 62 | console.log("Driver side rear door: " + "OPEN".red); 63 | } 64 | if (vehicle_state.pr) { 65 | console.log("Passenger side rear door: " + "OPEN".red); 66 | } 67 | if (vehicle_state.ft) { 68 | console.log("Front trunk: " + "OPEN".red); 69 | } 70 | if (vehicle_state.rt) { 71 | console.log("Rear trunk: " + "OPEN".red); 72 | } 73 | 74 | if (vehicle_state.sun_roof_installed) { 75 | var state = "CLOSED".green; 76 | 77 | if (vehicle_state.sun_roof_state != "unknown") { 78 | state = vehicle_state.sun_roof_state.toUpperCase().red; 79 | } 80 | 81 | console.log("Sunroof: " + state); 82 | } 83 | 84 | console.log("Firmware: " + vehicle_state.car_version.green); 85 | 86 | console.log("\nIs user present? ", vehicle_state.is_user_present ? "YES".yellow : "NO".green); 87 | 88 | str = vehicle_state.valet_mode ? "ON".bgGreen : "OFF".green; 89 | console.log("Valet mode: " + str + "\n"); 90 | }); 91 | } 92 | -------------------------------------------------------------------------------- /samples/soc.js: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // This sample demonstrates using TeslaJS 3 | // 4 | // https://github.com/mseminatore/TeslaJS 5 | // 6 | // Copyright (c) 2016 Mark Seminatore 7 | // 8 | // Refer to included LICENSE file for usage rights and restrictions 9 | //===================================================================== 10 | "use strict"; 11 | 12 | require('colors'); 13 | var program = require('commander'); 14 | var framework = require('./sampleFramework.js'); 15 | 16 | // 17 | // 18 | // 19 | program 20 | .option('-u, --username [string]', 'username (needed only if token not cached)') 21 | .option('-p, --password [string]', 'password (needed only if token not cached)') 22 | .option('-i, --index ', 'vehicle index (first car by default)', parseInt) 23 | .option('-U, --uri [string]', 'URI of test server (e.g. http://127.0.0.1:3000)') 24 | .parse(process.argv); 25 | 26 | // 27 | var sample = new framework.SampleFramework(program, sampleMain); 28 | sample.run(); 29 | 30 | function milesToKms(miles){ 31 | return miles * 1.609344; 32 | } 33 | 34 | // 35 | // 36 | // 37 | function sampleMain(tjs, options) { 38 | tjs.vehicleDataAsync(options).then( function(vehicleData) { 39 | // get the charge state info from the vehicle data 40 | var chargeState = vehicleData.charge_state; 41 | 42 | var eu_vehicle = vehicleData.vehicle_config.eu_vehicle; 43 | var unitsInKms = vehicleData.gui_settings.gui_distance_units === "km/hr"; 44 | 45 | var str = chargeState.charge_port_door_open === true ? "OPEN" : "CLOSED"; 46 | console.log("\nCharge port: " + str.green); 47 | 48 | if (chargeState.charging_state == "Charging") { 49 | console.log("Charging state: " + "Charging".green); 50 | 51 | var hours = Math.floor(chargeState.time_to_full_charge); 52 | var mins = Math.round((chargeState.time_to_full_charge - hours) * 60); 53 | 54 | str = "" 55 | if (hours > 0) { 56 | str = hours.toString().green + " hours "; 57 | } 58 | 59 | console.log("Time remaining: " + str + mins.toString().green + " minutes"); 60 | 61 | var mph = chargeState.charge_rate; 62 | 63 | console.log("Charge Rate: " + mph.toString().green + " mi/hr "); 64 | console.log("Power: " + chargeState.charger_voltage.toString().green + " V / " + chargeState.charger_actual_current.toString().green + " A"); 65 | 66 | } else if (chargeState.charging_state == "Disconnected") { 67 | console.log("Charging State: " + "Unplugged".bold.red); 68 | } else { 69 | console.log("Charging State: " + "Plugged In".green); 70 | } 71 | 72 | if (chargeState.scheduled_charging_pending) { 73 | var scheduledChargeTime = new Date(chargeState.scheduled_charging_start_time * 1000); 74 | console.log("Charge scheduled for " + scheduledChargeTime.toLocaleTimeString().toString().green); 75 | } 76 | 77 | console.log("\nCurrent charge level: " + chargeState.battery_level.toString().green + ' %'.green); 78 | console.log("Target charge level: " + chargeState.charge_limit_soc.toString().green + ' %'.green); 79 | 80 | console.log("\nRated range: " + (unitsInKms ? Math.round(milesToKms(chargeState.battery_range)).toString().green + ' km' : Math.round(chargeState.battery_range).toString().green + ' mi')); 81 | console.log((eu_vehicle?"Typical":"Ideal")+" range: " + (unitsInKms ? Math.round(milesToKms(chargeState.ideal_battery_range)).toString().green + ' km' : Math.round(chargeState.ideal_battery_range).toString().green + ' mi')); 82 | console.log("Projected range: " + (unitsInKms ? Math.round(milesToKms(chargeState.est_battery_range)).toString().green + ' km' : Math.round(chargeState.est_battery_range).toString().green + ' mi')); 83 | 84 | //console.log("\nRated - how far "+(eu_vehicle?"NEDC":"the EPA") + " says the car will go given their tests."); 85 | //console.log((eu_vehicle?"Typical":"Ideal")+" - how far the car will go if driven at a steady " + (unitsInKms? "88 km/h":"55 mph") + " on level ground at moderate temperatures."); 86 | //console.log("Projected - how far the car calculates you will go if you keep consuming power at the rate you are currently\n"); 87 | }); 88 | } 89 | -------------------------------------------------------------------------------- /src/auth.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | //process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0'; // Ignore 'UNABLE_TO_VERIFY_LEAF_SIGNATURE' authorization error 4 | 5 | var request = require('request').defaults({ 6 | headers: { 7 | "Accept" : "*/*" 8 | }, 9 | gzip: true, 10 | // timeout: 60000, 11 | // followRedirect: false, 12 | jar: true 13 | // ,proxy: "http://127.0.0.1:8888" // Note the fully-qualified path to Fiddler proxy. No "https" is required, even for https connections to outside. 14 | }); 15 | var crypto = require('crypto'); 16 | var Promise = require('promise'); 17 | 18 | exports.login = function login(credentials, callback) { 19 | var codeVerifier = generateCodeVerifier(); 20 | var codeChallenge = generateCodeChallenge(codeVerifier); 21 | var queryString = { 22 | // audience: '', 23 | client_id: 'ownerapi', 24 | code_challenge: codeChallenge, 25 | code_challenge_method: 'S256', 26 | locale: 'en', 27 | prompt: 'login', 28 | redirect_uri: 'https://auth.tesla.com/void/callback', 29 | response_type: 'code', 30 | scope: 'openid email offline_access', 31 | state: generateCodeChallenge(generateCodeVerifier()), 32 | login_hint: credentials.identity 33 | }; 34 | var transactionId = null; 35 | var loginHost = null; 36 | var loginUrl = null; 37 | 38 | req({ 39 | method: 'GET', 40 | url: 'https://auth.tesla.com/oauth2/v3/authorize', 41 | qs: queryString, 42 | headers: { 43 | "sec-fetch-site": "none", 44 | "sec-fetch-mode": "navigate", 45 | "sec-fetch-user": "?1", 46 | "sec-fetch-dest": "document" 47 | } 48 | }).then(function (result) { 49 | // Record the final URL we got redirected to; this is where we will send our credentials 50 | loginUrl = result.response.request.href; 51 | loginHost = "https://" + require('url').parse(loginUrl).host; 52 | var form = {}; 53 | 54 | var hiddenFormFields = result.body.match(/]+>/g); 55 | hiddenFormFields.forEach(function (field) { 56 | var name = field.match(/name="([^"]+)"/); 57 | var value = field.match(/value="([^"]*)"/); 58 | if (name && value) { 59 | form[name[1]] = value[1]; 60 | } 61 | }); 62 | 63 | transactionId = form.transaction_id; 64 | 65 | form.identity = credentials.identity; 66 | form.credential = credentials.credential; 67 | 68 | return req({ 69 | method: 'POST', 70 | url: loginUrl, 71 | form: form, 72 | headers: { 73 | "sec-fetch-site": "same-origin", 74 | "sec-fetch-mode": "navigate", 75 | "sec-fetch-user": "?1", 76 | "sec-fetch-dest": "document", 77 | "referer": loginUrl, 78 | "origin": loginHost 79 | } 80 | }); 81 | }).then(function (result) { 82 | if (result.body.includes('/oauth2/v3/authorize/mfa/verify')) { 83 | // MFA is required 84 | if (!credentials.mfaPassCode) { 85 | throw new Error("MFA passcode required"); 86 | } 87 | 88 | return mfaVerify(transactionId, loginHost, loginUrl, credentials.mfaPassCode, credentials.mfaDeviceName); 89 | } 90 | 91 | // No need to handle MFA 92 | return result; 93 | }).then(function (result) { 94 | var location = result.response.headers.location; 95 | if (!location) { 96 | throw new Error("Login credentials rejected"); 97 | } 98 | 99 | var url = require('url').parse(location, true); 100 | if (!url.query || !url.query.code) { 101 | throw new Error("No authorization code issued; credentials likely incorrect"); 102 | } 103 | 104 | return req({ 105 | method: 'POST', 106 | url: (url.query.issuer || 'https://auth.tesla.com/oauth2/v3') + '/token', 107 | jar: false, 108 | json: true, 109 | headers: { 110 | "Accept": "*/*", 111 | "Content-Type" : "application/json", 112 | "Connection" : "keep-alive" 113 | }, 114 | body: { 115 | grant_type: 'authorization_code', 116 | client_id: 'ownerapi', 117 | code_verifier: codeVerifier, 118 | code: url.query.code, 119 | redirect_uri: url.protocol + '//' + url.host + url.pathname 120 | } 121 | }); 122 | }).then(function (result) { 123 | return req({ 124 | method: 'POST', 125 | url: 'https://owner-api.teslamotors.com/oauth/token', 126 | headers: { 127 | Authorization: 'Bearer ' + result.body.access_token 128 | }, 129 | json: true, 130 | body: { 131 | grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer', 132 | client_id: _0x2dc0[0] 133 | } 134 | }); 135 | }).then(function (result) { 136 | callback(null, result.response, result.body); 137 | }).catch(function (error) { 138 | callback(error); 139 | }); 140 | } 141 | 142 | function mfaVerify(transactionId, host, referer, mfaPassCode, mfaDeviceName) { 143 | return req({ 144 | method: 'GET', 145 | url: host + '/oauth2/v3/authorize/mfa/factors?transaction_id=' + transactionId, 146 | headers: { 147 | "x-requested-with": "XMLHttpRequest", 148 | "sec-fetch-site": "same-origin", 149 | "sec-fetch-mode": "cors", 150 | "sec-fetch-dest": "empty", 151 | "referer": referer 152 | }, 153 | json: true 154 | }).then(function (result) { 155 | if (!result.body || !result.body.data || result.body.data.length == 0) { 156 | throw new Error('No MFA devices found'); 157 | } 158 | 159 | var device = result.body.data[0]; 160 | if (mfaDeviceName) { 161 | // Find the specific device we're looking for 162 | device = result.body.data.find(function (dev) { return dev.name == mfaDeviceName; }); 163 | if (!device) { 164 | throw new Error('No MFA device found with name ' + mfaDeviceName); 165 | } 166 | } 167 | 168 | return req({ 169 | method: 'POST', 170 | url: host + '/oauth2/v3/authorize/mfa/verify', 171 | headers: { 172 | "x-requested-with": "XMLHttpRequest", 173 | "origin": host, 174 | "sec-fetch-site": "same-origin", 175 | "sec-fetch-mode": "cors", 176 | "sec-fetch-dest": "empty", 177 | "referer": referer 178 | }, 179 | json: true, 180 | body: { 181 | transaction_id: transactionId, 182 | factor_id: device.id, 183 | passcode: mfaPassCode 184 | } 185 | }); 186 | }).then(function (result) { 187 | if (!result.body || !result.body.data || !result.body.data.approved || !result.body.data.valid) { 188 | throw new Error('MFA passcode rejected'); 189 | } 190 | 191 | // MFA auth has succeeded, so now repeat the authorize request with just the transaction id 192 | return req({ 193 | method: 'POST', 194 | url: referer, 195 | headers: { 196 | "sec-fetch-site": "same-origin", 197 | "sec-fetch-mode": "navigate", 198 | "sec-fetch-user": "?1", 199 | "sec-fetch-dest": "document", 200 | "referer": referer, 201 | "origin": host 202 | }, 203 | form: { 204 | transaction_id: transactionId 205 | }, 206 | json: true 207 | }); 208 | }); 209 | } 210 | 211 | function generateCodeVerifier() { 212 | // Tesla might use something more sophisticated, but in my experience it's a 112-char alphanumeric string so let's just do that 213 | var chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'; 214 | var random = crypto.randomBytes(86); 215 | var output = ''; 216 | for (var i = 0; i < random.length; i++) { 217 | output += chars[random[i] % chars.length]; 218 | } 219 | return output; 220 | } 221 | 222 | function generateCodeChallenge(verifier) { 223 | var hash = crypto.createHash('sha256'); 224 | hash.update(verifier); 225 | return hash.digest('base64') 226 | .replace(/=/g, '') 227 | .replace(/\+/g, '-') 228 | .replace(/\//g, '_'); 229 | } 230 | 231 | function req(parameters) { 232 | return new Promise(function (resolve, reject) { 233 | request(parameters, function (error, response, body) { 234 | if (error /*|| response.statusCode >= 400*/) { 235 | return reject(error || new Error("HTTP error " + response.statusCode)); 236 | } 237 | 238 | resolve({response: response, body: body}); 239 | }); 240 | }); 241 | } 242 | 243 | //var _0x2dc0 = ["\x65\x34\x61\x39\x39\x34\x39\x66\x63\x66\x61\x30\x34\x30\x36\x38\x66\x35\x39\x61\x62\x62\x35\x61\x36\x35\x38\x66\x32\x62\x61\x63\x30\x61\x33\x34\x32\x38\x65\x34\x36\x35\x32\x33\x31\x35\x34\x39\x30\x62\x36\x35\x39\x64\x35\x61\x62\x33\x66\x33\x35\x61\x39\x65", "\x63\x37\x35\x66\x31\x34\x62\x62\x61\x64\x63\x38\x62\x65\x65\x33\x61\x37\x35\x39\x34\x34\x31\x32\x63\x33\x31\x34\x31\x36\x66\x38\x33\x30\x30\x32\x35\x36\x64\x37\x36\x36\x38\x65\x61\x37\x65\x36\x65\x37\x66\x30\x36\x37\x32\x37\x62\x66\x62\x39\x64\x32\x32\x30"]; 244 | var _0x2dc0 = ["\x38\x31\x35\x32\x37\x63\x66\x66\x30\x36\x38\x34\x33\x63\x38\x36\x33\x34\x66\x64\x63\x30\x39\x65\x38\x61\x63\x30\x61\x62\x65\x66\x62\x34\x36\x61\x63\x38\x34\x39\x66\x33\x38\x66\x65\x31\x65\x34\x33\x31\x63\x32\x65\x66\x32\x31\x30\x36\x37\x39\x36\x33\x38\x34", "\x63\x37\x32\x35\x37\x65\x62\x37\x31\x61\x35\x36\x34\x30\x33\x34\x66\x39\x34\x31\x39\x65\x65\x36\x35\x31\x63\x37\x64\x30\x65\x35\x66\x37\x61\x61\x36\x62\x66\x62\x64\x31\x38\x62\x61\x66\x62\x35\x63\x35\x63\x30\x33\x33\x62\x30\x39\x33\x62\x62\x32\x66\x61\x33"]; 245 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # TeslaJS Change log 2 | 3 | Note that missing version entries are typically dependency updates for security. 4 | 5 | ## V4.10.0 6 | * merged several pull requests for new endpoints, remove password from remote start, bug fixes and added `vehicleById()` 7 | 8 | ## V4.9.8 9 | * Updated for latest changes to Tesla auth flow 10 | 11 | ## V4.9.4 12 | * fixed #210 streaming update to oauth 13 | 14 | ## V4.9.3 15 | * fixed #188 incorrect VIN for post 2018 cars 16 | 17 | ## V4.9.2 18 | * merged PR #191 added exports.promises object avoiding Async suffixes 19 | 20 | ## V4.8.1 21 | * merge PR to fix #92 homelink issue 22 | 23 | ## V4.7.9 24 | * added roadster to `vinDecode()` 25 | 26 | ## V4.7.0 27 | * added `maxDefrost()` 28 | 29 | ## V4.5.0 / 4.6.0 30 | * added `vinDecode()` 31 | 32 | ## V4.4.0 33 | * added `windowControl()` 34 | 35 | ## V4.3.2 36 | * updated dev deps 37 | 38 | ## V4.3.1 39 | * updated minified version 40 | 41 | ## V4.3.0 42 | * added `setSentryMode()` 43 | 44 | ## V4.2.1 45 | * updated teslajs.min.js 46 | 47 | ## V4.2.0 48 | * added `nearbyChargers()` 49 | 50 | ## V4.1.0 51 | * added seat heater and steering heater endpoints 52 | 53 | ## V4.0.1 54 | * bumped version 55 | 56 | ## V4.0.0 57 | * migrated to all lower-case 58 | 59 | ## V3.0.0 60 | * addressed #47 61 | 62 | ## V 2.1.49 63 | * updated dev dependencies to fix vulnerabilities #97 64 | 65 | ## V2.1.48 66 | * merged PR #101 to update README 67 | 68 | ## V2.1.47 69 | * added `setSpeed` sample 70 | 71 | ## V2.1.46 72 | * fix incorrect media endpoints 73 | 74 | ## V2.1.45 75 | * added navRequest sample 76 | * implemented media endpoints 77 | * added media samples 78 | 79 | ## V2.1.44 80 | * added minified version 81 | 82 | ## V2.1.43 83 | * added support for new software update and navigation endpoints 84 | * added samples that demonstrate new APIs 85 | 86 | ## V2.1.42 87 | * merged PR #91 to add progress callback to streaming 88 | * merged PR #96 to fix headers for JSON request bodies 89 | 90 | ## V2.1.41 91 | * updated `vehicles` sample to show vehicleData() call 92 | 93 | ## V2.1.40 94 | * updated `wakeup` sample to better show result 95 | 96 | ## V2.1.39 97 | * addressed #94 - Samples should be Model 3 aware 98 | 99 | ## V2.1.38 100 | * fixed doc errors 101 | 102 | ## V2.1.37 103 | * merge PR to re-enable `openTrunk()` API 104 | * added `openTrunk` sample 105 | 106 | ## V2.1.36 107 | * fixed #44 sunroof control and `sunroof` sample 108 | 109 | ## V2.1.35 110 | * added `vehicleConfig` sample 111 | 112 | ## v2.1.34 113 | * merged PR #85 to add vehicleConfig() endpoint call 114 | 115 | ## V2.1.33 116 | * fixed `homelink` sample cmd line parms #84 117 | 118 | ## V2.1.32 119 | * fixed README formatting 120 | 121 | ## V2.1.31 122 | * updated README to indicate that openChargePort also unlocks it #81 123 | 124 | ## V2.1.30 125 | * updated dependencies 126 | 127 | ## V2.1.29 128 | * fixed function typo in README #80 129 | 130 | ## V2.1.28 131 | * merged PR #78 to add support for `/data` REST endpoint 132 | * updated 133 | 134 | ## V2.1.27 135 | * fixed crash in setChargeLimit sample 136 | 137 | ## v2.1.26 138 | * small sample tweaks 139 | 140 | ## v2.1.25 141 | * added `refresh_token` property to obj return from `login()` and `refreshToken()` 142 | 143 | ## v2.1.24 144 | * added `refreshToken()` and test cases 145 | * updated samples to save/use full token payload 146 | 147 | ## v2.1.23 148 | * added `getVin()` and `getShortVin()` 149 | * added test cases 150 | 151 | ## v2.1.22 152 | * addressed #71 enhancing error handling 153 | 154 | ## v2.1.21 155 | * more test coverage 156 | * added global consts to docs 157 | 158 | ## v2.1.20 159 | * expanded docs 160 | 161 | ## v2.1.19 162 | * added header advertising of gzip #69 163 | 164 | ## v2.1.18 165 | * moved commander to devDependency, still used by samples 166 | * added more jsdocs tagging 167 | 168 | ## v2.1.17 169 | * removed old model id code from sampleFramework now using `getModel()` 170 | 171 | ## v2.1.16 172 | * added test case for `startStreaming()` 173 | * fixed incorrect login failure test case 174 | 175 | ## v2.1.15 176 | * added dependency checking badge to README 177 | * updated depdendencies 178 | * added login param checking 179 | * added test case for login failure 180 | 181 | ## v2.1.14 182 | * added jsdoc generation 183 | * fixed #66 crash in sampleFramework.js 184 | 185 | ## v2.1.13 186 | * added Code of Conduct 187 | 188 | ## Up through v2.1.11 189 | * addressed #60 issue with **simpleStreaming** sample 190 | * a number of documentation fixes and updates 191 | 192 | ## v2.1.6 193 | * address issue #58 Fixed **valet** sample failure with missing cmd line parm 194 | * address issue #57 Fixed **settemps** sample failure with missing cmd line parm 195 | * addresed issue #56 clamping error in **settemps** sample 196 | 197 | ## Up through v2.1.5 198 | * clarified paint color names to address #55 199 | 200 | ## Up through v2.1.3 201 | * updated docs for #53 and #54 202 | * addressed #53 and #54 by adding `getModel()` and `getPaintColor()` to return vehicle model and color 203 | * added more test cases and updated docs 204 | 205 | ## v2.1.0 206 | * addressed #47 by adding `vehicle()` and `allVehicles()` interfaces 207 | 208 | ## Up through v2.0.21 209 | * addressed #49 by removing `colors` dependency 210 | * samples still use `colors` 211 | 212 | ## v2.0.19 213 | * clamp charge level and temp inputs and expose new consts 214 | 215 | ## v2.0.15 216 | * added new samples **lock** and **unlock** 217 | 218 | ## v2.0.14 219 | * fixed jshint errors 220 | 221 | ## v2.0.12 222 | * `vehicles()` now updates options with vehicleID 223 | 224 | ## v2.0.10 225 | * added error checking to sunroof 226 | 227 | ## v2.0.9 228 | * switched to strict mode 229 | 230 | ## v2.0.8 231 | * updated documenation for removal of testla 232 | 233 | ## v2.0.7 234 | * added references to new **testla** sample location 235 | * removed **testla** and its depenencies 236 | * streamlined logic in request calls 237 | 238 | ## v2.0.6 239 | * removed err() and improved error handling 240 | * fixed contribution guidelines 241 | * added Project Principles and Contribution guidelines 242 | 243 | ## v2.0.4 244 | * fix missing tjs parameter to sampleMain 245 | * finish moving samples to new framework 246 | * revised more samples for new framework 247 | * added logo 248 | * sample factoring 249 | 250 | ## v2.0.3 251 | * fixed login example 252 | 253 | ## v2.0.2 254 | * removed github badges, too noisy 255 | * added samples to jshint coverage 256 | 257 | ## v2.0.1 258 | * fix badges 259 | * added github badges 260 | 261 | ## v2.0.0 262 | * revised documentation for 2.x 263 | * Finished fixing samples for Async changes 264 | * Finished Promise based *Async APIs 265 | 266 | ## v1.0.54 267 | * update tests and fix log level check 268 | * cleanup samples for jshint 269 | * enabling windows jshint testing 270 | * added new *always* log level 271 | 272 | ## v1.0.53 273 | * additional test cases 274 | * switched code coverage plan 275 | * updated to ignore coverage files 276 | 277 | ## v1.0.52 278 | * added jshint and fixed errors 279 | * start exploring code coverage 280 | 281 | ## v1.0.51 282 | * commented out sepia for now 283 | * added more test cases 284 | 285 | ## v1.0.50 286 | * added first test cases 287 | * Fixed `car_version` typo 288 | * fixed case and path issue in `require` 289 | * Removed relative pathing 290 | * updated node version for test coverage 291 | 292 | ## v1.0.49 293 | * started adding mocha test support 294 | 295 | ## v1.0.48 296 | * added build status badge 297 | * make tests succeed for now 298 | * started travis-ci integration 299 | 300 | ## v1.0.47 301 | * attempt to fix vehicle response parse issue 302 | 303 | ## v1.0.46 304 | * fixed sample bug #29 login fails due to missing email param 305 | 306 | ## v1.0.44 307 | * added Model X support 308 | 309 | ## v1.0.42 310 | * started to explore multi-car 311 | 312 | ## v1.0.41 313 | * checked in and documentaed non-working calendar sample 314 | 315 | ## v1.0.38 316 | * streaming works! 317 | * first working streaming version 318 | * fixed **login** sample error 319 | 320 | ## v1.0.37 321 | * fixed **login** and **soc** samples, updated readme 322 | 323 | ## v1.0.36 324 | * progress on calendar, not yet working 325 | 326 | ## v1.0.35 327 | * added start of jquery support to **testla** sample 328 | * added homelink support 329 | 330 | ## v1.0.32 331 | * added charging simulation to **testla** 332 | 333 | ## v1.0.30 334 | * updated web views for **testla** 335 | 336 | ## v1.0.28 337 | * all web views can update server state in **testla** 338 | * drivestate updated by webview in **testla** 339 | 340 | ## v1.0.27 341 | * updated for ENV variables and colors 342 | * updated sample cmd line help 343 | 344 | ## v1.0.26 345 | * big updates to **testla** 346 | 347 | ## v1.0.25 348 | * added error handlers 349 | * added start of new apis, added logging 350 | * renamed **mockla** to **testla** 351 | 352 | ## v1.0.24 353 | * updated time remaining for charging 354 | 355 | ## v1.0.22 356 | * added state change tracking to **mockla** 357 | * added **guiSettings** and **mobileEnabled** samples 358 | 359 | ## v1.0.21 360 | * updates for **mockla** sample 361 | * updated more samples for **mockla** 362 | 363 | ## v1.0.19 364 | * added beginnings of **mockla** sample and support 365 | * add ability to change baseURI 366 | 367 | ## v1.0.18 368 | * updated description for npm 369 | * added multi-vehicle support to samples 370 | 371 | ## v1.0.17 372 | * updated for new samples 373 | * added multi-vehicle suppport 374 | * updated all samples for new cmd line 375 | * added new cmd line processing 376 | 377 | ## v1.0.16 378 | * added **sunroof** sample, fixed bugs in **setTemps** and **vehicle** samples 379 | 380 | ## v1.0.15 381 | * fixed issue with setTemps sample 382 | 383 | ## v1.0.14 384 | * added **setTemps** sample, updated **setChargeLimit** sample 385 | 386 | ## v1.0.13 387 | * added **setChargeLimit** sample 388 | 389 | ## v1.0.12 390 | * added **remoteStart** sample 391 | 392 | ## v1.0.11 393 | * added `colors` support 394 | 395 | ## v1.0.9 396 | * add **geoloc** sample 397 | 398 | ## v1.0.8 399 | * add `reset_valet_pin()` and `close_charge_port()` APIs 400 | 401 | ## v1.0.7 402 | * added **openChargePort** sample 403 | * added **wakup** sample 404 | 405 | ## v1.0.5 406 | * renamed samples to match APIs 407 | * update samples, add **valet** sample 408 | 409 | ## v1.0.4 410 | * add POST body logging 411 | 412 | ## v1.0.3 413 | * renamed npm package 414 | 415 | ## v1.0.0 416 | * publish 1.0.0 via npm 417 | -------------------------------------------------------------------------------- /teslajs.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file This is a Node.js module encapsulating the unofficial Tesla API set 3 | * 4 | * Github: https://github.com/mseminatore/TeslaJS 5 | * NPM: https://www.npmjs.com/package/teslajs 6 | * 7 | * @copyright Copyright (c) 2016 Mark Seminatore 8 | * 9 | * @license MIT 10 | * 11 | * Refer to included LICENSE file for usage rights and restrictions 12 | */ 13 | "use strict";var request=require("request").defaults({headers:{"x-tesla-user-agent":"TeslaApp/3.4.4-350/fad4a582e/android/8.1.0","user-agent":"Mozilla/5.0 (Linux; Android 8.1.0; Pixel XL Build/OPM4.171019.021.D1; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/68.0.3440.91 Mobile Safari/537.36"},json:!0,gzip:!0,body:{}}),Promise=require("promise"),websocket=require("ws"),streamingPortal="wss://streaming.vn.teslamotors.com/streaming/";exports.streamingPortal=streamingPortal;var streamingBaseURI=process.env.TESLAJS_STREAMING||streamingPortal,portal="https://owner-api.teslamotors.com";exports.portal=portal;var portalBaseURI=process.env.TESLAJS_SERVER||portal,API_LOG_ALWAYS=0;exports.API_LOG_ALWAYS=API_LOG_ALWAYS;var API_ERR_LEVEL=1;exports.API_ERR_LEVEL=API_ERR_LEVEL;var API_CALL_LEVEL=2;exports.API_CALL_LEVEL=API_CALL_LEVEL;var API_RETURN_LEVEL=3;exports.API_RETURN_LEVEL=API_RETURN_LEVEL;var API_BODY_LEVEL=4;exports.API_BODY_LEVEL=API_BODY_LEVEL;var API_REQUEST_LEVEL=5;exports.API_REQUEST_LEVEL=API_REQUEST_LEVEL;var API_RESPONSE_LEVEL=6;exports.API_RESPONSE_LEVEL=API_RESPONSE_LEVEL;var API_LOG_ALL=255;exports.API_LOG_ALL=API_LOG_ALL;var logLevel=process.env.TESLAJS_LOG||0;function log(e,o){logLevel Note: If you are planning to purchase a Tesla you can get 1,000 miles of free supercharging using this referral [link](http://ts.la/mark5257). 13 | 14 | ### This library currently supports all existing Tesla vehicles. 15 | 16 | First, it is important to acknowledge that there are already several very 17 | good Javascript libraries available for the Tesla. So why create another 18 | one? Rather than contribute to or modify one or more of the existing 19 | libraries, this library was created for two main reasons: 20 | 21 | 1. The anticipated need for a few small but important features that existing 22 | libraries did not provide 23 | 2. I was looking for a personal opportunity to learn more about the Tesla REST 24 | API, NodeJS, Express and Git/GitHub 25 | 26 | ## Notable Features 27 | 28 | With the introduction of the new OAuth-based owner API, one of the features I 29 | wanted was the ability to make API calls without having to login each time a 30 | new process was invoked. Many existing libraries require a login transaction 31 | with each initiation of the library. With the TeslaJS library, once an auth 32 | token is retrieved it can be cached and used to make other Tesla REST API 33 | calls. For certain use cases, notably server logging of multiple vehicles, 34 | this can be important for moderating load on the Tesla login servers. 35 | 36 | This is also important if you want to use the library to do server-based data 37 | logging. It is generally safer to store an OAuth token on the server rather 38 | than logon credentials. If the server is compromised only the OAuth token is 39 | at risk and all existing tokens can be invalidated by changing the password on 40 | the account. 41 | 42 | Another feature that I wanted was API stateless-ness (achieved via an **options** 43 | parameter to API calls) so that it was possible to use the library to make 44 | multiple overlapping async calls for different vehicles for data-logging. 45 | 46 | ## What's New! 47 | 48 | You can read the complete history of changes in the 49 | [CHANGELOG](https://github.com/mseminatore/TeslaJS/blob/master/CHANGELOG.md). 50 | 51 | Here are some of the more recent features and fixes: 52 | 53 | 1. In **V4.10.0** merged #275 to fix #273, added new endpoints, bug fixes 54 | 2. In **V4.9.8** updated for latest changes to Tesla auth flow 55 | 3. In **V4.9.4** fixed #210 streaming update to oauth 56 | 4. In **V4.9.3** fixed #188 incorrect VIN for post 2018 cars 57 | 5. In **V4.9.2** merged PR #191 added exports.promises object avoiding Async suffixes 58 | 59 | ## Migrating Major Version Changes 60 | 61 | You can find instructions on how to migrate across major version changes by reading 62 | the [MIGRATION](https://github.com/mseminatore/TeslaJS/blob/master/MIGRATION.md) guide. 63 | 64 | ## Known Issues 65 | 66 | 1. The homelink API appears to require Autopilot hardware. Can someone with 67 | AP test and report back? 68 | 2. Calendar support not yet functional. If someone can share the JSON for a 69 | valid calendar request that would help! 70 | 71 | ## Library Users 72 | 73 | A growing number of projects use the library or are based on its code, examples: 74 | 75 | - [Tesla Control](https://www.teslacontrol.app) app in the Windows Store. This 76 | Universal Windows App runs on Windows desktop, Windows Phone and Xbox. 77 | - [Nikola](https://github.com/geraldoramos/nikola) app on Github. This is a cross-platform app built with [Electron](https://github.com/electron/electron), currently available for macOS and Windows. 78 | 79 | 80 | ## Project Principles 81 | 82 | This project has a few principles that have and will continue to guide its 83 | development. 84 | 85 | 1. **Dependency lean**. Try to keep the required dependencies to a minimum. 86 | 2. **Comprehensive**. Attempt to expose the full Tesla REST API surface area. 87 | 3. **Simple**. Using the library should be simple and straightforward 88 | following common conventions. 89 | 4. **Server friendly**. Provide for use based on auth tokens and avoid 90 | requiring access to passwords. 91 | 92 | ## Documentation 93 | 94 | We've recently added auto-generated documentation via [jsdocs](https://www.npmjs.com/package/jsdoc). See the 95 | [DOCS](https://github.com/mseminatore/TeslaJS/blob/master/docs/DOCS.md) 96 | for a mostly complete reference. Please let us know if you see something 97 | missing and we will continue to expand. 98 | 99 | ## Contributing 100 | 101 | Contributions are welcome, particularly bug fixes and enhancements! 102 | Refer to our [Contribution Guidelines](https://github.com/mseminatore/TeslaJS/blob/master/CONTRIBUTING.md) for details. 103 | 104 | > Please note that Project owners reserve the right to accept or reject any PR 105 | > for any reason. 106 | 107 | ## Code of Conduct 108 | 109 | Before contributing or participating in the TeslaJS community please be sure to 110 | familiarize yourself with our project 111 | [CODE OF CONDUCT](https://github.com/mseminatore/TeslaJS/blob/master/CODE_OF_CONDUCT.md). 112 | These guidelines are intended to govern interactions with and within the TeslaJS 113 | community. 114 | 115 | # Tesla API Documentation 116 | 117 | The Tesla REST API encapsulated by this library was documented through the 118 | collaboration of many Tesla owners. Please thank and support them for their 119 | continued efforts! The latest REST API documentation can be found [here](https://tesla-api.timdorr.com/) 120 | 121 | # Warranty Disclaimer 122 | 123 | You may use this library with the understanding that doing so is 124 | **AT YOUR OWN RISK**. No warranty, express or implied, is made with regards 125 | to the fitness or safety of this code for any purpose. If you use this 126 | library to query or change settings of your vehicle you understand that it 127 | is possible to make changes that could inadvertently lower the security of 128 | your vehicle, or cause damage, through actions including but not limited to: 129 | 130 | * Unlocking the vehicle 131 | * Remotely starting the vehicle 132 | * Opening the sunroof 133 | * Opening the frunk or trunk 134 | * Lowering the battery charge level 135 | * Impacting the long-term health of your battery 136 | 137 | > Please be careful not to use this code in a way that loads the Tesla servers 138 | > with too many concurrent requests. Calling the Tesla REST APIs at a very high 139 | > frequency will stress the Tesla servers and could get your IP or favorite 140 | > cloud service blocked by Tesla. Or in the worst case it could cause Tesla 141 | > to revoke the key that enables access via this and many other libraries. 142 | 143 | # Installation 144 | 145 | In order to use the library and/or samples you must first download and install 146 | [NodeJS](http://nodejs.org). An installable TeslaJS module for [npm](http://npmjs.org) 147 | is now available. 148 | 149 | To download and install the library and all of its dependencies to a local 150 | project directory use the following: 151 | 152 | npm install teslajs 153 | 154 | If you prefer to download and install the library globally for all future 155 | node projects you may use: 156 | 157 | npm install -g teslajs 158 | 159 | You may also install directly from the GitHub 160 | [source](https://github.com/mseminatore/TeslaJS). Either download and unzip 161 | the source, or clone the repository. 162 | 163 | > Remember, whether you install via ZIP source or Git clone you must install 164 | > the dependencies before using TeslaJS. 165 | 166 | To install dependencies via npm, from the root level of the library directory 167 | type: 168 | 169 | npm install 170 | 171 | This library and its accomanying samples are under active development. New 172 | features, samples and bug fixes are being added regularly. To ensure that 173 | you have the very latest version of TeslaJS and it's dependencies be sure to 174 | update frequently. 175 | 176 | To do so, from your project directory type: 177 | 178 | npm update 179 | 180 | # Library Usage Examples 181 | 182 | ## Login Example 183 | 184 | As you can see below, it is very simple to login and acquire an OAuth token. 185 | 186 | ```javascript 187 | var tjs = require('teslajs'); 188 | 189 | var username = ""; 190 | var password = ""; 191 | var mfaPassCode = ""; 192 | 193 | tjs.login({ 194 | username: username, 195 | password: password, 196 | mfaPassCode: mfaPassCode 197 | }, function(err, result) { 198 | if (result.error) { 199 | console.log(JSON.stringify(result.error)); 200 | process.exit(1); 201 | } 202 | 203 | var token = JSON.stringify(result.authToken); 204 | 205 | if (token) 206 | console.log("Login Succesful!"); 207 | }); 208 | ``` 209 | 210 | > Note: Currently the only way to invalidate an issued token is to change your 211 | > MyTesla account password. Therefore, you must take care to properly secure 212 | > tokens. Do not share them over an unsecure connection, or store them on a 213 | > public machine. 214 | 215 | ## Vehicle Example 216 | 217 | With the OAuth token from a successful `login()` API call you can query the 218 | vehicle for the account: 219 | 220 | ```javascript 221 | var options = { authToken: result.authToken }; 222 | tjs.vehicle(options, function (err, vehicle) { 223 | console.log("Vehicle " + vehicle.vin + " is: " + vehicle.state); 224 | }); 225 | ``` 226 | 227 | Or using the Async Promise-based calls: 228 | 229 | ```javascript 230 | tjs.vehicleAsync(options).done(function(vehicle) { 231 | console.log("Vehicle " + vehicle.vin + " is: " + vehicle.state); 232 | }); 233 | ``` 234 | 235 | ## Charge State Example 236 | 237 | Adding the vehicle ID from a successful `vehicle()` API call to options you can 238 | make other Tesla REST calls: 239 | 240 | ```javascript 241 | var options = { authToken: result.authToken, vehicleID: vehicle.id_s }; 242 | tjs.chargeState(options, function (err, chargeState) { 243 | console.log("Current charge level: " + chargeState.battery_level + '%'); 244 | }); 245 | ``` 246 | 247 | And using the Async Promise-based calls: 248 | 249 | ```javascript 250 | tjs.chargeStateAsync(options).done(function(chargeState) { 251 | console.log("Current charge level: " + chargeState.battery_level + '%'); 252 | }); 253 | ``` 254 | 255 | Or using the Async version of the `vehicleData()` API call: 256 | 257 | ```javascript 258 | tjs.vehicleDataAsync(options).done(function(vehicleData) { 259 | var chargeState = vehicleData.charge_state; 260 | console.log("Current charge level: " + chargeState.battery_level + '%'); 261 | }); 262 | 263 | ``` 264 | 265 | # Library Interfaces 266 | 267 | The TeslaJS library exports a number of methods and constants. The library 268 | also responds to some environment variables. 269 | 270 | ## Environment Variables 271 | 272 | ENV variable | Description 273 | ------------ | ----------- 274 | TESLAJS_LOG | if set defines the value of the default logging level ([See constants](#library-exported-constants)) 275 | TESLAJS_SERVER | if set defines the URI for the Tesla servers (e.g. set to http://127.0.0.1:3000) 276 | TESLAJS_STREAMING | if set defines the URI for the Tesla streaming servers (e.g. set to http://127.0.0.1:3000) 277 | 278 | ## General API Calls 279 | 280 | These methods all require an `options` parameter with at least `options.authToken` defined. 281 | 282 | Function | Description 283 | -------- | ----------- 284 | getLogLevel() | gets the level of debug logging 285 | setLogLevel() | sets the level of debug logging 286 | getVin() | return the VIN from the vehicle object 287 | getShortVin() | return short form VIN from the vehicle object 288 | getPortalBaseURI() | gets the server URI 289 | setPortalBaseURI() | sets the server for testing, pass null to reset 290 | login() | authenticate with Tesla servers and retrieve the OAuth token 291 | logout() | delete the current OAuth token 292 | vehicle() | return information on the requested vehicle defined by `carIndex` in `options` 293 | vehicleById() | return information on the requested vehicle defined by `vehicleID` in `options` 294 | vehicles() | return information and option data for all vehicles 295 | getModel(vehicle) | returns the Tesla model as a string from vehicle object 296 | getPaintColor(vehicle) | returns the paint color as a string from vehicle object 297 | products() | returns an array of the Tesla products owned by the user 298 | solarStatus() | returns information on a particular solar site defined by `sideId` in `options` 299 | 300 | ## Vehicle-specific API calls 301 | 302 | These methods all require an `options` parameter with at least `options.authToken` and `options.vehicleID` defined. 303 | 304 | > **Note**: Vehicle objects from the API contain *three* different strings that look like potential candidates for `vehicleID`. The correct one is `id_s`, and __**not**__ `id` or `vehicle_id`. Using the wrong ID will result in **404** errors! 305 | 306 | > **Note**: The promise-based versions of the APIs have the suffix **Async** appended. 307 | > For example `vehicle()` and `vehicleAsync()`. Note that not all APIs have an Async version, for example streaming. 308 | 309 | Function | Description 310 | -------- | ----------- 311 | cancelSoftwareUpdate() | cancels a previously scheduled software update 312 | chargeState() | retrieve the charge_state data 313 | chargeStandard() | set the charge limit to 90% 314 | chargeMaxRange() | sets the charge limit to 100% 315 | climateState() | retrieve the climate_state data 316 | climateStart() | turn on the HVAC system 317 | climateStop() | turn off the HVAC system 318 | closeChargePort() | close the charge port on appropriately equipped vehicles 319 | doorLock() | locks the doors 320 | doorUnlock() | unlocks the doors 321 | driveState() | retrieve the drive_state data 322 | flashLights() | flashes the headlights 323 | guiSettings() | retrieves the GUI settings 324 | homelink() | triggers homelink from the vehicle 325 | honkHorn() | honks the horn 326 | maxDefrost() | toggles climate between Max Defrost and the previous setting 327 | mediaTogglePlayback() | toggles media playback 328 | mediaPlayNext() | plays the next track 329 | mediaPlayPrevious() | plays the previous track 330 | mediaPlayNextFavorite() | plays the next favorite 331 | mediaPlayPreviousFavorite() | plays the previous favorite 332 | mediaVolumeUp() | increase the volume 333 | mediaVolumeDown() | decrease the volume 334 | mobileEnabled() | returns whether mobile access is enabled 335 | navigationRequest() | send a navigation request to the vehicle 336 | nearbyChargers() | returns a list of nearby destination and superchargers 337 | openChargePort() | opens the charge port, or releases the latch if the charge port is open, a cable is plugged in, and charging is stopped 338 | openTrunk() | open the trunk or frunk 339 | refreshToken() | retrieve new OAuth token from refresh token 340 | remoteStart() | enables remote starting of the car 341 | resetValetPin() | reset the valet pin 342 | scheduleSoftwareUpdate() | schedule a firmware update 343 | seatHeater() | adjust seat heating level 344 | setChargeLimit() | sets the charge limit to a specific amount 345 | setSentryMode() | enables or disables sentry mode 346 | setTemps() | set driver/passenger temp set points (in Deg.C) 347 | setValetMode() | set/reset valet mode 348 | speedLimitActivate() | activate the speed limit 349 | speedLimitDeactivate() | deactivate the speed limit 350 | speedLimitClearPin() | clear the speed limit pin 351 | speedLimitSetLimit() | set the speed limit 352 | startCharge() | initiates a charging session 353 | startStreaming() | initiate a streaming data session 354 | steeringHeater() | adjust the steering wheel heater 355 | stopCharge() | terminates a charging session 356 | sunRoofControl() | put the sunroof into a specific state 357 | sunRoofMove() | open the sunroof to a specific percent 358 | vehicleData() | retrieve **all** vehicle state data in a single call 359 | vehicleConfig() | retrieve the vehicle_config data 360 | vehicleState() | retrieve the vehicle_state data 361 | vinDecode() | decode and return the vehicle VIN properties 362 | wakeUp() | attempt to wake a sleeping vehicle 363 | windowControl() | adjust windows to 'vent' or 'close' position 364 | 365 | ## Library Exported Constants 366 | 367 | Constant | Description 368 | -------- | ----------- 369 | streamingPortal | the URI for the streaming API portal 370 | portal | the base URI for the OAuth-based API portal 371 | API_LOG_ALWAYS | log this message always 372 | API_CALL_LEVEL | log all API calls 373 | API_RETURN_LEVEL | log all API calls and completions 374 | API_REQUEST_LEVEL | log all API requests 375 | API_RESPONSE_LEVEL | log all API responses 376 | API_BODY_LEVEL | log calls and completions as well as the body of POST commands 377 | API_LOG_ALL | the highest level of logging 378 | CHARGE_STORAGE | charge to 50% 379 | CHARGE_STANDARD | charge to 90% 380 | CHARGE_RANGE | charge to 100%. Tesla recommends against frequent usage! 381 | MAX_TEMP | maximum temperature for climate system 382 | MIN_TEMP | minimum temperature for climate system 383 | SUNROOF_CLOSED | closes the sunroof 384 | SUNROOF_VENT | open the sunroof to the vent position 385 | streamingColumns | an array of the available streaming columns 386 | FRUNK | constant for openTrunk API 387 | TRUNK | constant for openTrunk API 388 | 389 | Most of the APIs take both an **options** parameter and an optional 390 | **callback** function. The **options** parameter must always contain a 391 | property called **authToken** that contains the OAuth token returned 392 | from a successfull `login()`. For all APIs that act on a specific 393 | vehicle the **options** parameter must also contain a **vehicleID** 394 | member that contains the long vehicle ID value (ie. `id_s`) returned from a successful 395 | call to `vehicle()`. 396 | 397 | By default the `vehicle()` API returns information on the first vehicle 398 | returned. By providing a **carIndex** member in the **options** parameter 399 | information on a specific vehicle can be queried. 400 | 401 | # Samples 402 | 403 | A collection of samples are provided in the `samples` directory. These demonstrate 404 | some basic usage scenarios for the library. To use the samples first: 405 | 406 | cd samples 407 | node sampleName 408 | 409 | After running the [login](#loginjs) sample an auth token will be cached locally. 410 | 411 | If you prefer to avoid keeping an auth token on your machine, provide login 412 | credentials on the command line for each sample. This will perform a login 413 | request and keep the token only for the duration of the sample. The 414 | difference lies in whether you are more comfortable with the security of a 415 | file associated with an account in your file system vs. the visibility of 416 | your login credentials in the process table for the lifetime of the sample. 417 | 418 | ## List of Samples 419 | 420 | Sample | Description 421 | ------ | ----------- 422 | [login](#loginjs) | Login and acquire an OAuth token. Cached to the local directory 423 | [logout](#logoutjs) | Delete the locally cached OAuth token if present 424 | [cancelUpdate](#cancelupdatejs) | Cancels a previously scheduled software update 425 | [climate](#climatejs) | Display the current state of the HVAC system 426 | [climateStart](#climatestartjs) | Turn on the HVAC system 427 | [climateStop](#climatestopjs) | Turn off the HVAC system 428 | [flashLights](#flashlightsjs) | Flash the headlights 429 | [geoloc](#geolocjs) | Display the current GPS location of the vehicle 430 | [guiSettings](#guisettingsjs) | Display the current unit format settings 431 | [homelink](#homelinkjs) | Trigger homelink (note appears to require AP hardware) 432 | [honkHorn](#honkhornjs) | Honk the horn 433 | [lock](#lockjs) | Lock the car doors 434 | [media](#mediajs) | Sends commands to the vehicle media system 435 | [mobileEnabled](#mobileenabledjs) | Display whether remote access is enabled 436 | [navRequest](#navrequestjs) | Send an address to the vehicle 437 | [odometer](#odometerjs) | Displays the current odometer value 438 | [openChargePort](#openchargeportjs) | Opens the charge port, or releases the latch if the charge port is open, a cable is plugged in, and charging is stopped 439 | [openTrunk](#opentrunkjs) | Opens the FRUNK or opens/closes the trunk 440 | [products](#productsjs) | Displays a list of Tesla products owned and their details 441 | [resetValetPin](#resetvaletpinjs) | Resets the valet mode pin 442 | [remoteStart](#remotestartjs) | Enables driving without the key fob present 443 | [scheduleUpdate](#scheduleupdatejs) | Schedules a software update for installation 444 | [setChargeLimit](#setchargelimitjs) | Set the battery charge limit to the given value 445 | [setSpeed](#setspeedjs) | Sets the speed limit 446 | [setTemps](#settempsjs) | Set the driver and passenger temperatures to the given value 447 | [simpleStreaming](#simplestreamingjs) | Demonstrates basic use of the streaming API 448 | [soc](#socjs) | Displays the current battery State of Charge (SOC) for the vehicle 449 | [startCharge](#startchargejs) | Initiate a charging session 450 | [stopCharge](#stopchargejs) | Terminate a charging session 451 | [sunroof](#sunroofjs) | Control the sunroof. Be careful! 452 | [unlock](#unlockjs) | Unlock the car doors 453 | [valet](#valetjs) | Enable or disable valet mode 454 | [vehicle](#vehiclejs) | Retrieve and display information on the current vehicle state 455 | [vehicleConfig](#vehicleConfigjs) | Retrieve and display information on the current vehicle configuration 456 | [wakeup](#wakeupjs) | Send a wakeup command to the vehicle 457 | 458 | ## login.js 459 | 460 | This sample demonstrates the basic login process which returns the OAuth token required for other API calls. The sample 461 | writes out a file called **.token** which stores the OAuth token. Other samples will use this cached token, if present, 462 | to avoid the need to request the **username** and **password** and login redundantly via the Tesla servers. 463 | 464 | > If you prefer not to have your OAuth token stored locally do not run this sample. Instead you may run the samples and provide 465 | > the **username** and **password** each time on the command line. 466 | 467 | Usage: 468 | 469 | node login.js [options] username password 470 | 471 | Options: 472 | 473 | -h, --help output usage information 474 | -U, --uri [string] URI of test server (e.g. http://127.0.0.1:3000) 475 | 476 | ([top](#teslajs)) 477 | 478 | ## logout.js 479 | 480 | This sample deletes the locally cached **.token** file if present. 481 | 482 | Usage: 483 | 484 | node logout.js 485 | 486 | ([top](#teslajs)) 487 | 488 | ## cancelUpdate.js 489 | 490 | This sample cancels a previously scheduled software update for the vehicle. 491 | 492 | Usage: 493 | 494 | node cancelUpdate.js [options] 495 | 496 | Options: 497 | 498 | -h, --help output usage information 499 | -u, --username [string] username (needed only if token not cached) 500 | -p, --password [string] password (needed only if token not cached) 501 | -i, --index vehicle index (first car by default) 502 | -U, --uri [string] URI of test server (e.g. http://127.0.0.1:3000) 503 | 504 | ([top](#teslajs)) 505 | 506 | ## climate.js 507 | 508 | This sample retrieves and displays the **climate_state** data on the HVAC system of the vehicle. 509 | 510 | Usage: 511 | 512 | node climate.js [options] 513 | 514 | Options: 515 | 516 | -h, --help output usage information 517 | -u, --username [string] username (needed only if token not cached) 518 | -p, --password [string] password (needed only if token not cached) 519 | -i, --index vehicle index (first car by default) 520 | -U, --uri [string] URI of test server (e.g. http://127.0.0.1:3000) 521 | 522 | ([top](#teslajs)) 523 | 524 | ## climateStart.js 525 | 526 | This sample demonstrates turning on the HVAC system of the vehicle. 527 | 528 | Usage: 529 | 530 | node climateStart.js [options] 531 | 532 | Options: 533 | 534 | -h, --help output usage information 535 | -u, --username [string] username (needed only if token not cached) 536 | -p, --password [string] password (needed only if token not cached) 537 | -i, --index vehicle index (first car by default) 538 | -U, --uri [string] URI of test server (e.g. http://127.0.0.1:3000) 539 | 540 | ([top](#teslajs)) 541 | 542 | ## climateStop.js 543 | 544 | This sample demonstrates turning off the HVAC system of the vehicle. 545 | 546 | Usage: 547 | 548 | node climateStop.js [options] 549 | 550 | Options: 551 | 552 | -h, --help output usage information 553 | -u, --username [string] username (needed only if token not cached) 554 | -p, --password [string] password (needed only if token not cached) 555 | -i, --index vehicle index (first car by default) 556 | -U, --uri [string] URI of test server (e.g. http://127.0.0.1:3000) 557 | 558 | ([top](#teslajs)) 559 | 560 | ## flashLights.js 561 | 562 | This sample demonstrates flashing the headlights of the vehicle. 563 | 564 | Usage: 565 | 566 | node flashLights.js [options] 567 | 568 | Options: 569 | 570 | -h, --help output usage information 571 | -u, --username [string] username (needed only if token not cached) 572 | -p, --password [string] password (needed only if token not cached) 573 | -i, --index vehicle index (first car by default) 574 | -U, --uri [string] URI of test server (e.g. http://127.0.0.1:3000) 575 | 576 | ([top](#teslajs)) 577 | 578 | ## geoloc.js 579 | 580 | This sample retrieves and displays information on the location and driving state of the car using the **drive_state** query. 581 | 582 | Usage: 583 | 584 | node geoloc.js [options] 585 | 586 | Options: 587 | 588 | -h, --help output usage information 589 | -u, --username [string] username (needed only if token not cached) 590 | -p, --password [string] password (needed only if token not cached) 591 | -g, --geocode geocode (reverse geocode to nearest address) 592 | -i, --index vehicle index (first car by default) 593 | -U, --uri [string] URI of test server (e.g. http://127.0.0.1:3000) 594 | 595 | ([top](#teslajs)) 596 | 597 | ## guiSettings.js 598 | 599 | This sample retrieves and displays the current display formats for the user interface. 600 | 601 | Usage: 602 | 603 | node guiSettings.js [options] 604 | 605 | Options: 606 | 607 | -h, --help output usage information 608 | -u, --username [string] username (needed only if token not cached) 609 | -p, --password [string] password (needed only if token not cached) 610 | -i, --index vehicle index (first car by default) 611 | -U, --uri [string] URI of test server (e.g. http://127.0.0.1:3000) 612 | 613 | ([top](#teslajs)) 614 | 615 | ## homelink.js 616 | 617 | This sample demonstrates triggering homelink via the vehicle. 618 | 619 | >Note: This feature appears to be tied to the presence of Autopilot hardware and software. Looking for validation 620 | >on both AP and pre-AP vehicles. 621 | 622 | Usage: 623 | 624 | node homelink.js [options] 625 | 626 | Options: 627 | 628 | -h, --help output usage information 629 | -u, --username [string] username (needed only if token not cached) 630 | -p, --password [string] password (needed only if token not cached) 631 | -i, --index vehicle index (first car by default) 632 | -U, --uri [string] URI of test server (e.g. http://127.0.0.1:3000) 633 | 634 | ([top](#teslajs)) 635 | 636 | ## honkHorn.js 637 | 638 | This sample demonstrates honking the horn of the vehicle. 639 | 640 | Usage: 641 | 642 | node honkHorn.js [options] 643 | 644 | Options: 645 | 646 | -h, --help output usage information 647 | -u, --username [string] username (needed only if token not cached) 648 | -p, --password [string] password (needed only if token not cached) 649 | -i, --index vehicle index (first car by default) 650 | -U, --uri [string] URI of test server (e.g. http://127.0.0.1:3000) 651 | 652 | ([top](#teslajs)) 653 | 654 | ## lock.js 655 | 656 | This sample demonstrates locking the doors of the vehicle. 657 | 658 | Usage: 659 | 660 | node lock.js [options] 661 | 662 | Options: 663 | 664 | -h, --help output usage information 665 | -u, --username [string] username (needed only if token not cached) 666 | -p, --password [string] password (needed only if token not cached) 667 | -i, --index vehicle index (first car by default) 668 | -U, --uri [string] URI of test server (e.g. http://127.0.0.1:3000) 669 | 670 | ([top](#teslajs)) 671 | 672 | ## media.js 673 | 674 | This sample sends a command to the vehicle media system. 675 | 676 | Usage: 677 | 678 | node media.js [options] toggle|next|prev|next_fav|prev_fav|up|down 679 | 680 | Options: 681 | 682 | -h, --help output usage information 683 | -u, --username [string] username (needed only if token not cached) 684 | -p, --password [string] password (needed only if token not cached) 685 | -i, --index vehicle index (first car by default) 686 | -U, --uri [string] URI of test server (e.g. http://127.0.0.1:3000) 687 | 688 | ([top](#teslajs)) 689 | 690 | ## mobileEnabled.js 691 | 692 | This sample retrieves and displays whether mobile access is enabled. 693 | 694 | Usage: 695 | 696 | node mobileEnabled.js [options] 697 | 698 | Options: 699 | 700 | -h, --help output usage information 701 | -u, --username [string] username (needed only if token not cached) 702 | -p, --password [string] password (needed only if token not cached) 703 | -i, --index vehicle index (first car by default) 704 | -U, --uri [string] URI of test server (e.g. http://127.0.0.1:3000) 705 | 706 | ([top](#teslajs)) 707 | 708 | ## navRequest.js 709 | 710 | This sample sends an address to the vehicle navigation system. 711 | 712 | Usage: 713 | 714 | node navRequest.js [options] subject text [locale] 715 | 716 | subject - the short-version of the destination name 717 | text - the name and address of the destination 718 | locale - the locale, if not present defaults to en-US 719 | 720 | Options: 721 | 722 | -h, --help output usage information 723 | -u, --username [string] username (needed only if token not cached) 724 | -p, --password [string] password (needed only if token not cached) 725 | -i, --index vehicle index (first car by default) 726 | -U, --uri [string] URI of test server (e.g. http://127.0.0.1:3000) 727 | 728 | ([top](#teslajs)) 729 | 730 | ## odometer.js 731 | 732 | This sample retrieves and displays the current vehicle odometer value. 733 | 734 | Usage: 735 | 736 | node odometer.js [options] 737 | 738 | Options: 739 | 740 | -h, --help output usage information 741 | -u, --username [string] username (needed only if token not cached) 742 | -p, --password [string] password (needed only if token not cached) 743 | -i, --index vehicle index (first car by default) 744 | -U, --uri [string] URI of test server (e.g. http://127.0.0.1:3000) 745 | 746 | ([top](#teslajs)) 747 | 748 | ## openChargePort.js 749 | 750 | This sample sends the command to open the charge port, or to release the latch if 751 | the charge port is open, a cable is plugged in, and charging is stopped. 752 | 753 | Usage: 754 | 755 | node openChargePort.js [options] 756 | 757 | Options: 758 | 759 | -h, --help output usage information 760 | -u, --username [string] username (needed only if token not cached) 761 | -p, --password [string] password (needed only if token not cached) 762 | -i, --index vehicle index (first car by default) 763 | -U, --uri [string] URI of test server (e.g. http://127.0.0.1:3000) 764 | 765 | ([top](#teslajs)) 766 | 767 | ## openTrunk.js 768 | 769 | This sample sends the command to open or close the trunk or frunk. On current 770 | model vehicles only the trunk can currently be closed. 771 | 772 | Usage: 773 | 774 | node openTrunk.js [options] trunk|frunk 775 | 776 | Options: 777 | 778 | -h, --help output usage information 779 | -u, --username [string] username (needed only if token not cached) 780 | -p, --password [string] password (needed only if token not cached) 781 | -i, --index vehicle index (first car by default) 782 | -U, --uri [string] URI of test server (e.g. http://127.0.0.1:3000) 783 | 784 | ([top](#teslajs)) 785 | 786 | ## products.js 787 | 788 | This sample requests information on the Tesla products owned by the authenticated user. 789 | 790 | Usage: 791 | 792 | node products.js [options] 793 | 794 | Options: 795 | 796 | -h, --help output usage information 797 | -u, --username [string] username (needed only if token not cached) 798 | -p, --password [string] password (needed only if token not cached) 799 | -U, --uri [string] URI of test server (e.g. http://127.0.0.1:3000) 800 | 801 | ([top](#teslajs)) 802 | 803 | ## remoteStart.js 804 | 805 | This sample enables remotely starting the vehicle without a key fob present. 806 | 807 | Usage: 808 | 809 | node remoteStart.js [options] 810 | 811 | Options: 812 | 813 | -h, --help output usage information 814 | -u, --username [string] username (needed only if token not cached) 815 | -i, --index vehicle index (first car by default) 816 | -U, --uri [string] URI of test server (e.g. http://127.0.0.1:3000) 817 | 818 | ([top](#teslajs)) 819 | 820 | ## resetValetPin.js 821 | 822 | This sample attempts to reset the current valet pin. 823 | 824 | Usage: 825 | 826 | node resetValetPin.js [options] 827 | 828 | Options: 829 | 830 | -h, --help output usage information 831 | -u, --username [string] username (needed only if token not cached) 832 | -p, --password [string] password (needed only if token not cached) 833 | -i, --index vehicle index (first car by default) 834 | -U, --uri [string] URI of test server (e.g. http://127.0.0.1:3000) 835 | 836 | ([top](#teslajs)) 837 | 838 | ## scheduleUpdate.js 839 | 840 | This sample schedules a pending software update for installation. 841 | 842 | Usage: 843 | 844 | node scheduleUpdate.js [options] delay 845 | 846 | Options: 847 | 848 | -h, --help output usage information 849 | -u, --username [string] username (needed only if token not cached) 850 | -p, --password [string] password (needed only if token not cached) 851 | -i, --index vehicle index (first car by default) 852 | -U, --uri [string] URI of test server (e.g. http://127.0.0.1:3000) 853 | 854 | ([top](#teslajs)) 855 | 856 | ## setChargeLimit.js 857 | 858 | This sample sets the current battery charge limit to the given value. 859 | 860 | Usage: 861 | 862 | node setChargeLimit.js [options] number|standard|storage|range 863 | 864 | Options: 865 | 866 | -h, --help output usage information 867 | -u, --username [string] username (needed only if token not cached) 868 | -p, --password [string] password (needed only if token not cached) 869 | -i, --index vehicle index (first car by default) 870 | -U, --uri [string] URI of test server (e.g. http://127.0.0.1:3000) 871 | 872 | ([top](#teslajs)) 873 | 874 | ## setSpeed.js 875 | 876 | This sample sets the speed limit to the given value. 877 | 878 | Usage: 879 | 880 | node setTemps.js [options] speed 881 | 882 | Options: 883 | 884 | -h, --help output usage information 885 | -u, --username [string] username (needed only if token not cached) 886 | -p, --password [string] password (needed only if token not cached) 887 | -i, --index vehicle index (first car by default) 888 | -U, --uri [string] URI of test server (e.g. http://127.0.0.1:3000) 889 | 890 | ([top](#teslajs)) 891 | 892 | ## setTemps.js 893 | 894 | This sample sets the driver and passenger temperature to the given value. 895 | 896 | Usage: 897 | 898 | node setTemps.js [options] temperature 899 | 900 | Options: 901 | 902 | -h, --help output usage information 903 | -u, --username [string] username (needed only if token not cached) 904 | -p, --password [string] password (needed only if token not cached) 905 | -i, --index vehicle index (first car by default) 906 | -U, --uri [string] URI of test server (e.g. http://127.0.0.1:3000) 907 | 908 | ([top](#teslajs)) 909 | 910 | ## simpleStreaming.js 911 | 912 | This sample demonstrates basic use of the streaming API to retrieve real-time vehicle data. 913 | 914 | Usage: 915 | 916 | node simpleStreaming.js [options] 917 | 918 | Options: 919 | 920 | -h, --help output usage information 921 | -i, --index vehicle index (first car by default) 922 | -U, --uri [string] URI of test server (e.g. http://127.0.0.1:3000) 923 | 924 | ([top](#teslajs)) 925 | 926 | ## soc.js 927 | 928 | This sample retrieves the **charge_state** information and displays the charge limit, the current 929 | vehicle charge level, and the ideal, rated and projected range. 930 | 931 | Usage: 932 | 933 | node soc.js [options] 934 | 935 | Options: 936 | 937 | -h, --help output usage information 938 | -u, --username [string] username (needed only if token not cached) 939 | -p, --password [string] password (needed only if token not cached) 940 | -i, --index vehicle index (first car by default) 941 | -U, --uri [string] URI of test server (e.g. http://127.0.0.1:3000) 942 | 943 | ([top](#teslajs)) 944 | 945 | ## startCharge.js 946 | 947 | This sample demonstrates how to initiate a charging session. 948 | 949 | Usage: 950 | 951 | node startCharge.js [options] 952 | 953 | Options: 954 | 955 | -h, --help output usage information 956 | -u, --username [string] username (needed only if token not cached) 957 | -p, --password [string] password (needed only if token not cached) 958 | -i, --index vehicle index (first car by default) 959 | -U, --uri [string] URI of test server (e.g. http://127.0.0.1:3000) 960 | 961 | ([top](#teslajs)) 962 | 963 | ## stopCharge.js 964 | 965 | This sample demonstrates how to terminate a charging session. 966 | 967 | Usage: 968 | 969 | node stopCharge.js [options] 970 | 971 | Options: 972 | 973 | -h, --help output usage information 974 | -u, --username [string] username (needed only if token not cached) 975 | -p, --password [string] password (needed only if token not cached) 976 | -i, --index vehicle index (first car by default) 977 | -U, --uri [string] URI of test server (e.g. http://127.0.0.1:3000) 978 | 979 | ([top](#teslajs)) 980 | 981 | ## sunroof.js 982 | 983 | This sample demonstrates controlling the panoramic sunroof if present. 984 | 985 | Usage: 986 | 987 | node sunroof.js [options] close|vent 988 | 989 | Options: 990 | 991 | -h, --help output usage information 992 | -u, --username [string] username (needed only if token not cached) 993 | -p, --password [string] password (needed only if token not cached) 994 | -i, --index vehicle index (first car by default) 995 | -U, --uri [string] URI of test server (e.g. http://127.0.0.1:3000) 996 | 997 | ([top](#teslajs)) 998 | 999 | ## unlock.js 1000 | 1001 | This sample demonstrates unlocking the doors of the vehicle. 1002 | 1003 | Usage: 1004 | 1005 | node unlock.js [options] 1006 | 1007 | Options: 1008 | 1009 | -h, --help output usage information 1010 | -u, --username [string] username (needed only if token not cached) 1011 | -p, --password [string] password (needed only if token not cached) 1012 | -i, --index vehicle index (first car by default) 1013 | -U, --uri [string] URI of test server (e.g. http://127.0.0.1:3000) 1014 | 1015 | ([top](#teslajs)) 1016 | 1017 | ## vehicle.js 1018 | 1019 | This sample retrives and displays several elements of data returned from the **vehicle_state** REST API. 1020 | 1021 | Usage: 1022 | 1023 | node vehicle.js [options] 1024 | 1025 | Options: 1026 | 1027 | -h, --help output usage information 1028 | -u, --username [string] username (needed only if token not cached) 1029 | -p, --password [string] password (needed only if token not cached) 1030 | -i, --index vehicle index (first car by default) 1031 | -U, --uri [string] URI of test server (e.g. http://127.0.0.1:3000) 1032 | 1033 | ([top](#teslajs)) 1034 | 1035 | ## vehicleConfig.js 1036 | 1037 | This sample retrives and displays several elements of data returned from the **vehicle_config** REST API. 1038 | 1039 | Usage: 1040 | 1041 | node vehicleConfig.js [options] 1042 | 1043 | Options: 1044 | 1045 | -h, --help output usage information 1046 | -u, --username [string] username (needed only if token not cached) 1047 | -p, --password [string] password (needed only if token not cached) 1048 | -i, --index vehicle index (first car by default) 1049 | -U, --uri [string] URI of test server (e.g. http://127.0.0.1:3000) 1050 | 1051 | ([top](#teslajs)) 1052 | 1053 | ## valet.js 1054 | 1055 | This sample enables or disables valet mode. 1056 | 1057 | Usage: 1058 | 1059 | node valet.js [options] ON|OFF pincode 1060 | 1061 | Options: 1062 | 1063 | -h, --help output usage information 1064 | -u, --username [string] username (needed only if token not cached) 1065 | -p, --password [string] password (needed only if token not cached) 1066 | -i, --index vehicle index (first car by default) 1067 | -U, --uri [string] URI of test server (e.g. http://127.0.0.1:3000) 1068 | 1069 | ([top](#teslajs)) 1070 | 1071 | ## wakeup.js 1072 | 1073 | This sample sends a wakeup signal to wake a vehicle in sleep mode. 1074 | 1075 | Usage: 1076 | 1077 | node wakeup.js [options] 1078 | 1079 | Options: 1080 | 1081 | -h, --help output usage information 1082 | -u, --username [string] username (needed only if token not cached) 1083 | -p, --password [string] password (needed only if token not cached) 1084 | -i, --index vehicle index (first car by default) 1085 | -U, --uri [string] URI of test server (e.g. http://127.0.0.1:3000) 1086 | 1087 | [Back to Top](#teslajs) 1088 | -------------------------------------------------------------------------------- /apiary.apib: -------------------------------------------------------------------------------- 1 | FORMAT: 1A 2 | HOST: https://owner-api.teslamotors.com 3 | 4 | # TeslaJS Mock Model S JSON API 5 | 6 | This is unofficial documentation of the Tesla Model S JSON API used by the iOS and Android apps. 7 | Its primary purpose is to enable testing the TeslaJS node library. 8 | 9 | # Group Authentication 10 | 11 | ## Login [/oauth/token] 12 | 13 | ### Get an Access Token [POST] 14 | 15 | Performs the login. Takes in an plain text email and password, matching the owner's login information for [https://my.teslamotors.com/user/login](https://my.teslamotors.com/user/login). 16 | 17 | Returns a `access_token` which is passed along as a header with all future requests to authenticate the user. 18 | 19 | You must provide the `Authorization: Bearer {access_token}` header in all other requests. 20 | 21 | The current client ID and secret are [available here](http://pastebin.com/fX6ejAHd) 22 | 23 | + Attributes 24 | 25 | + grant_type: `password` (string) - The type of oAuth grant. Always "password" 26 | + client_id: `abc` (string) - The oAuth client ID 27 | + client_secret: `123` (string) - The oAuth client secret 28 | + email: `elon@teslamotors.com` (string) - The email for my.teslamotors.com 29 | + password: `edisonsux` (string) - The password for my.teslamotors.com 30 | 31 | + Response 200 (application/json) 32 | 33 | + Body 34 | 35 | { 36 | "access_token": "abc123", 37 | "token_type": "bearer", 38 | "expires_in": 7776000, 39 | "created_at": 1457385291, 40 | "refresh_token" : "cba321" 41 | } 42 | 43 | ## Logout [/oauth/revoke] 44 | 45 | ### Revoke an Access Token [POST] 46 | 47 | Revoke an access token 48 | 49 | + Request 50 | 51 | + Headers 52 | 53 | Authorization: Bearer {access_token} 54 | 55 | + Response 200 (application/json) 56 | 57 | + Body 58 | 59 | { 60 | "response": true 61 | } 62 | 63 | # Group Vehicles 64 | 65 | A logged in user can have multiple vehicles under their account. This resource is primarily responsible for listing the vehicles and the basic details about them. 66 | 67 | ## Vehicle Collection [/api/1/vehicles] 68 | 69 | ### List all Vehicles [GET] 70 | 71 | Retrieve a list of your owned vehicles (includes vehicles not yet shipped!) 72 | 73 | + Request 74 | 75 | + Headers 76 | 77 | Authorization: Bearer {access_token} 78 | 79 | + Response 200 (application/json) 80 | 81 | + Body 82 | 83 | { 84 | "response": [{ 85 | "color": null, 86 | "display_name": null, 87 | "id": 321, 88 | "option_codes": "MS01,RENA,TM00,DRLH,PF00,BT85,PBCW,RFPO,WT19,IBMB,IDPB,TR00,SU01,SC01,TP01,AU01,CH00,HP00,PA00,PS00,AD02,X020,X025,X001,X003,X007,X011,X013", 89 | "user_id": 123, 90 | "vehicle_id": 1234567890, 91 | "vin": "5YJSA1CN5CFP01657", 92 | "tokens": ["x", "x"], 93 | "state": "online" 94 | }], 95 | "count":1 96 | } 97 | 98 | ### Get specific Vehicle [GET /api/1/vehicles/{vehicle_id}] 99 | Retrieve a specific vehicle (includes vehicles not yet shipped!) 100 | 101 | + Request 102 | 103 | + Headers 104 | 105 | Authorization: Bearer {access_token} 106 | 107 | + Response 200 (application/json) 108 | 109 | + Body 110 | 111 | { 112 | "response": { 113 | "color": null, 114 | "display_name": null, 115 | "id": 321, 116 | "option_codes": "MS01,RENA,TM00,DRLH,PF00,BT85,PBCW,RFPO,WT19,IBMB,IDPB,TR00,SU01,SC01,TP01,AU01,CH00,HP00,PA00,PS00,AD02,X020,X025,X001,X003,X007,X011,X013", 117 | "user_id": 123, 118 | "vehicle_id": 1234567890, 119 | "vin": "5YJSA1CN5CFP01657", 120 | "tokens": ["x", "x"], 121 | "state": "online" 122 | }, 123 | "count":1 124 | } 125 | 126 | ## State and Settings [/api/1/vehicles/{vehicle_id}] 127 | 128 | These resources are read-only and determine the state of the vehicle's various sub-systems. 129 | 130 | + Parameters 131 | 132 | + vehicle_id: `1` (number) - The id of the Vehicle. 133 | 134 | ## Mobile Access [GET /api/1/vehicles/{vehicle_id}/mobile_enabled] 135 | 136 | Determines if mobile access to the vehicle is enabled. 137 | 138 | + Request 139 | 140 | + Headers 141 | 142 | Authorization: Bearer {access_token} 143 | 144 | + Parameters 145 | 146 | + vehicle_id: `1` (number) - The id of the Vehicle. 147 | 148 | + Response 200 (application/json) 149 | 150 | + Body 151 | 152 | { 153 | "response": true 154 | } 155 | 156 | ## Data [GET /api/1/vehicles/{vehicle_id}/data] 157 | 158 | A "legacy" version of the data endpoint. 159 | 160 | Currently, this has the exact same response structure as the newer vehicle_data endpoint. 161 | 162 | + Request 163 | 164 | + Headers 165 | 166 | Authorization: Bearer {access_token} 167 | 168 | + Parameters 169 | 170 | + vehicle_id: `1` (number) - The id of the Vehicle. 171 | 172 | + Response 200 (application/json) 173 | 174 | + Body 175 | 176 | { 177 | "response": { 178 | "color": null, 179 | "display_name": null, 180 | "id": 321, 181 | "option_codes": "MS01,RENA,TM00,DRLH,PF00,BT85,PBCW,RFPO,WT19,IBMB,IDPB,TR00,SU01,SC01,TP01,AU01,CH00,HP00,PA00,PS00,AD02,X020,X025,X001,X003,X007,X011,X013", 182 | "user_id": 123, 183 | "vehicle_id": 1234567890, 184 | "vin": "5YJSA1CN5CFP01657", 185 | "tokens": ["x", "x"], 186 | "state": "online", 187 | "charge_state": { 188 | "charging_state": "Complete", 189 | "charge_to_max_range": false, 190 | "max_range_charge_counter": 0, 191 | "fast_charger_present": false, 192 | "battery_range": 239.02, 193 | "est_battery_range": 155.79, 194 | "ideal_battery_range": 275.09, 195 | "battery_level": 91, 196 | "battery_current": -0.6, 197 | "charge_starting_range": null, 198 | "charge_starting_soc": null, 199 | "charger_voltage": 0, 200 | "charger_pilot_current": 40, 201 | "charger_actual_current": 0, 202 | "charger_power": 0, 203 | "time_to_full_charge": null, 204 | "charge_rate": -1.0, 205 | "motorized_charge_port": false, 206 | "charge_energy_added": 14.74, 207 | "charge_miles_added_rated": 50, 208 | "charge_miles_added_ideal": 58, 209 | "charge_port_door_open": true }, 210 | "climate_state": { 211 | "inside_temp": 17.0, 212 | "outside_temp": 9.5, 213 | "driver_temp_setting": 22.6, 214 | "passenger_temp_setting": 22.6, 215 | "is_auto_conditioning_on": false, 216 | "is_front_defroster_on": null, 217 | "is_rear_defroster_on": false, 218 | "fan_status": 0 }, 219 | "drive_state": { 220 | "shift_state": null, 221 | "speed": null, 222 | "latitude": 33.794839, 223 | "longitude": -84.401593, 224 | "heading": 4, 225 | "gps_as_of": 1359863204 }, 226 | "gui_settings": { 227 | "gui_distance_units": "mi/hr", 228 | "gui_temperature_units": "F", 229 | "gui_charge_rate_units": "mi/hr", 230 | "gui_24_hour_time": false, 231 | "gui_range_display": "Rated" }, 232 | "mobile_enabled": true, 233 | "vehicle_state": { 234 | "df": false, 235 | "dr": false, 236 | "pf": false, 237 | "pr": false, 238 | "ft": false, 239 | "rt": false, 240 | "car_version": "1.19.42", 241 | "locked": true, 242 | "sun_roof_installed": false, 243 | "sun_roof_state": "unknown", 244 | "sun_roof_percent_open": 0, 245 | "dark_rims": false, 246 | "wheel_type": "Base19", 247 | "has_spoiler": false, 248 | "roof_color": "Colored", 249 | "perf_config": "Base" } 250 | } 251 | } 252 | 253 | 254 | ## Data [GET /api/1/vehicles/{vehicle_id}/vehicle_data] 255 | 256 | Returns all vehicle data in a single call. Highly recommended to use this 257 | instead of individual calls as it lowers overall load on Tesla servers. 258 | 259 | + Request 260 | 261 | + Headers 262 | 263 | Authorization: Bearer {access_token} 264 | 265 | + Parameters 266 | 267 | + vehicle_id: `1` (number) - The id of the Vehicle. 268 | 269 | + Response 200 (application/json) 270 | 271 | + Body 272 | 273 | { 274 | "response": { 275 | "color": null, 276 | "display_name": null, 277 | "id": 321, 278 | "option_codes": "MS01,RENA,TM00,DRLH,PF00,BT85,PBCW,RFPO,WT19,IBMB,IDPB,TR00,SU01,SC01,TP01,AU01,CH00,HP00,PA00,PS00,AD02,X020,X025,X001,X003,X007,X011,X013", 279 | "user_id": 123, 280 | "vehicle_id": 1234567890, 281 | "vin": "5YJSA1CN5CFP01657", 282 | "tokens": ["x", "x"], 283 | "state": "online", 284 | "charge_state": { 285 | "charging_state": "Complete", 286 | "charge_to_max_range": false, 287 | "max_range_charge_counter": 0, 288 | "fast_charger_present": false, 289 | "battery_range": 239.02, 290 | "est_battery_range": 155.79, 291 | "ideal_battery_range": 275.09, 292 | "battery_level": 91, 293 | "battery_current": -0.6, 294 | "charge_starting_range": null, 295 | "charge_starting_soc": null, 296 | "charger_voltage": 0, 297 | "charger_pilot_current": 40, 298 | "charger_actual_current": 0, 299 | "charger_power": 0, 300 | "time_to_full_charge": null, 301 | "charge_rate": -1.0, 302 | "motorized_charge_port": false, 303 | "charge_energy_added": 14.74, 304 | "charge_miles_added_rated": 50, 305 | "charge_miles_added_ideal": 58, 306 | "charge_port_door_open": true }, 307 | "climate_state": { 308 | "inside_temp": 17.0, 309 | "outside_temp": 9.5, 310 | "driver_temp_setting": 22.6, 311 | "passenger_temp_setting": 22.6, 312 | "is_auto_conditioning_on": false, 313 | "is_front_defroster_on": null, 314 | "is_rear_defroster_on": false, 315 | "fan_status": 0 }, 316 | "drive_state": { 317 | "shift_state": null, 318 | "speed": null, 319 | "latitude": 33.794839, 320 | "longitude": -84.401593, 321 | "heading": 4, 322 | "gps_as_of": 1359863204 }, 323 | "gui_settings": { 324 | "gui_distance_units": "mi/hr", 325 | "gui_temperature_units": "F", 326 | "gui_charge_rate_units": "mi/hr", 327 | "gui_24_hour_time": false, 328 | "gui_range_display": "Rated" }, 329 | "mobile_enabled": true, 330 | "vehicle_state": { 331 | "df": false, 332 | "dr": false, 333 | "pf": false, 334 | "pr": false, 335 | "ft": false, 336 | "rt": false, 337 | "car_version": "1.19.42", 338 | "locked": true, 339 | "sun_roof_installed": false, 340 | "sun_roof_state": "unknown", 341 | "sun_roof_percent_open": 0, 342 | "dark_rims": false, 343 | "wheel_type": "Base19", 344 | "has_spoiler": false, 345 | "roof_color": "Colored", 346 | "perf_config": "Base" } 347 | } 348 | } 349 | 350 | ## Charge State [GET /api/1/vehicles/{vehicle_id}/data_request/charge_state] 351 | 352 | Returns the state of charge in the battery. 353 | 354 | + Request 355 | 356 | + Headers 357 | 358 | Authorization: Bearer {access_token} 359 | 360 | + Parameters 361 | 362 | + vehicle_id: `1` (number) - The id of the Vehicle. 363 | 364 | + Response 200 (application/json) 365 | 366 | + Body 367 | 368 | { 369 | "response": { 370 | "charging_state": "Complete", 371 | "charge_to_max_range": false, 372 | "max_range_charge_counter": 0, 373 | "fast_charger_present": false, 374 | "battery_range": 239.02, 375 | "est_battery_range": 155.79, 376 | "ideal_battery_range": 275.09, 377 | "battery_level": 91, 378 | "battery_current": -0.6, 379 | "charge_starting_range": null, 380 | "charge_starting_soc": null, 381 | "charger_voltage": 0, 382 | "charger_pilot_current": 40, 383 | "charger_actual_current": 0, 384 | "charger_power": 0, 385 | "time_to_full_charge": null, 386 | "charge_rate": -1.0, 387 | "motorized_charge_port": false, 388 | "charge_energy_added": 14.74, 389 | "charge_miles_added_rated": 50, 390 | "charge_miles_added_ideal": 58, 391 | "charge_port_door_open": true 392 | } 393 | } 394 | 395 | ## Climate Settings [GET /api/1/vehicles/{vehicle_id}/data_request/climate_state] 396 | 397 | Returns the current temperature and climate control state. 398 | 399 | + Request 400 | 401 | + Headers 402 | 403 | Authorization: Bearer {access_token} 404 | 405 | + Parameters 406 | 407 | + vehicle_id: `1` (number) - The id of the Vehicle. 408 | 409 | + Response 200 (application/json) 410 | 411 | + Body 412 | 413 | { 414 | "response": { 415 | "inside_temp": 17.0, 416 | "outside_temp": 9.5, 417 | "driver_temp_setting": 22.6, 418 | "passenger_temp_setting": 22.6, 419 | "is_auto_conditioning_on": false, 420 | "is_front_defroster_on": null, 421 | "is_rear_defroster_on": false, 422 | "fan_status": 0 423 | } 424 | } 425 | 426 | ## Driving and Position [GET /api/1/vehicles/{vehicle_id}/data_request/drive_state] 427 | 428 | Returns the driving and position state of the vehicle. 429 | 430 | + Request 431 | 432 | + Headers 433 | 434 | Authorization: Bearer {access_token} 435 | 436 | + Parameters 437 | 438 | + vehicle_id: `1` (number) - The id of the Vehicle. 439 | 440 | + Response 200 (application/json) 441 | 442 | + Body 443 | 444 | { 445 | "response": { 446 | "shift_state": null, 447 | "speed": null, 448 | "latitude": 33.794839, 449 | "longitude": -84.401593, 450 | "heading": 4, 451 | "gps_as_of": 1359863204 452 | } 453 | } 454 | 455 | ## GUI Settings [GET /api/1/vehicles/{vehicle_id}/data_request/gui_settings] 456 | 457 | Returns various information about the GUI settings of the car, such as unit format and range display. 458 | 459 | + Request 460 | 461 | + Headers 462 | 463 | Authorization: Bearer {access_token} 464 | 465 | + Parameters 466 | 467 | + vehicle_id: `1` (number) - The id of the Vehicle. 468 | 469 | + Response 200 (application/json) 470 | 471 | + Body 472 | 473 | { 474 | "response": { 475 | "gui_distance_units": "mi/hr", 476 | "gui_temperature_units": "F", 477 | "gui_charge_rate_units": "mi/hr", 478 | "gui_24_hour_time": false, 479 | "gui_range_display": "Rated" 480 | } 481 | } 482 | 483 | ## Vehicle State [GET /api/1/vehicles/{vehicle_id}/data_request/vehicle_state] 484 | 485 | Returns the vehicle's physical state, such as which doors are open. 486 | 487 | + Request 488 | 489 | + Headers 490 | 491 | authorization: Bearer {access_token} 492 | 493 | + Parameters 494 | 495 | + vehicle_id: `1` (number) - The id of the Vehicle. 496 | 497 | + Response 200 (application/json) 498 | 499 | + Body 500 | 501 | { 502 | "response": { 503 | "df": false, 504 | "dr": false, 505 | "pf": false, 506 | "pr": false, 507 | "ft": false, 508 | "rt": false, 509 | "car_version": "1.19.42", 510 | "locked": true, 511 | "sun_roof_installed": false, 512 | "sun_roof_state": "unknown", 513 | "sun_roof_percent_open": 0, 514 | "dark_rims": false, 515 | "wheel_type": "Base19", 516 | "has_spoiler": false, 517 | "roof_color": "Colored", 518 | "perf_config": "Base" 519 | } 520 | } 521 | 522 | ## Vehicle Config [GET /api/1/vehicles/{vehicle_id}/data_request/vehicle_config] 523 | 524 | Returns the vehicle's configuration details. 525 | 526 | + Request 527 | 528 | + Headers 529 | 530 | authorization: Bearer {access_token} 531 | 532 | + Parameters 533 | 534 | + vehicle_id: `1` (number) - The id of the Vehicle. 535 | 536 | + Response 200 (application/json) 537 | 538 | + Body 539 | 540 | { 541 | "response": { 542 | "car_special_type":"base", 543 | "car_type":"s", 544 | "eu_vehicle":false, 545 | "exterior_color":"Black", 546 | "has_ludicrous_mode":false, 547 | "motorized_charge_port":false, 548 | "perf_config":"P2", 549 | "plg":true, 550 | "rear_seat_heaters":0, 551 | "rear_seat_type":0, 552 | "rhd":false, 553 | "roof_color":"None", 554 | "seat_type":0, 555 | "spoiler_type":"None", 556 | "sun_roof_installed":1, 557 | "third_row_seats":"None", 558 | "timestamp":1506198725145, 559 | "trim_badging":"p85", 560 | "wheel_type":"Base19" 561 | } 562 | } 563 | 564 | # Group Vehicle Commands 565 | 566 | These commands alter the vehicles state, and return result (true/false) to indicate success, and if failure reason contains the cause of failure. 567 | 568 | ## Wake Up Car [POST /api/1/vehicles/{vehicle_id}/wake_up] 569 | 570 | Wakes up the car from the sleep state. Necessary to get some data from the car. 571 | 572 | + Request 573 | 574 | + Headers 575 | 576 | Authorization: Bearer {access_token} 577 | 578 | + Parameters 579 | 580 | + vehicle_id: `1` (number) - The id of the Vehicle. 581 | 582 | + Response 200 (application/json) 583 | 584 | + Body 585 | 586 | { 587 | "response": { 588 | "result": true, 589 | "reason": "" 590 | } 591 | } 592 | 593 | ## Schedule Software Update [POST /api/1/vehicles/{vehicle_id}/command/schedule_software_update?offset_sec={offset_sec}] 594 | 595 | Schedules the car to install a pending firmware Update 596 | 597 | + Request 598 | 599 | + Headers 600 | 601 | Authorization: Bearer {access_token} 602 | 603 | + Parameters 604 | 605 | + vehicle_id: `1` (number) - The id of the Vehicle. 606 | + offset_sec: `0` (number) - The number of ms before installation. 607 | 608 | + Response 200 (application/json) 609 | 610 | + Body 611 | 612 | { 613 | "response": { 614 | "result": true, 615 | "reason": "" 616 | } 617 | } 618 | 619 | ## Cancel Software Update [POST /api/1/vehicles/{vehicle_id}/command/cancel_software_update] 620 | 621 | Cancels a pending firmware Update 622 | 623 | + Request 624 | 625 | + Headers 626 | 627 | Authorization: Bearer {access_token} 628 | 629 | + Parameters 630 | 631 | + vehicle_id: `1` (number) - The id of the Vehicle. 632 | 633 | + Response 200 (application/json) 634 | 635 | + Body 636 | 637 | { 638 | "response": { 639 | "result": true, 640 | "reason": "" 641 | } 642 | } 643 | 644 | ## Media toggle playback [POST /api/1/vehicles/{vehicle_id}/command/media_toggle_playback] 645 | 646 | Toggles media playback 647 | 648 | + Request 649 | 650 | + Headers 651 | 652 | Authorization: Bearer {access_token} 653 | 654 | + Parameters 655 | 656 | + vehicle_id: `1` (number) - The id of the Vehicle. 657 | 658 | + Response 200 (application/json) 659 | 660 | + Body 661 | 662 | { 663 | "response": { 664 | "result": true, 665 | "reason": "" 666 | } 667 | } 668 | 669 | ## Media play next track [POST /api/1/vehicles/{vehicle_id}/command/media_next_track] 670 | 671 | Play the next track 672 | 673 | + Request 674 | 675 | + Headers 676 | 677 | Authorization: Bearer {access_token} 678 | 679 | + Parameters 680 | 681 | + vehicle_id: `1` (number) - The id of the Vehicle. 682 | 683 | + Response 200 (application/json) 684 | 685 | + Body 686 | 687 | { 688 | "response": { 689 | "result": true, 690 | "reason": "" 691 | } 692 | } 693 | 694 | ## Media play previous track [POST /api/1/vehicles/{vehicle_id}/command/media_prev_track] 695 | 696 | Play the previous track 697 | 698 | + Request 699 | 700 | + Headers 701 | 702 | Authorization: Bearer {access_token} 703 | 704 | + Parameters 705 | 706 | + vehicle_id: `1` (number) - The id of the Vehicle. 707 | 708 | + Response 200 (application/json) 709 | 710 | + Body 711 | 712 | { 713 | "response": { 714 | "result": true, 715 | "reason": "" 716 | } 717 | } 718 | 719 | ## Media play next favorite [POST /api/1/vehicles/{vehicle_id}/command/media_next_fav] 720 | 721 | Play the next favorite 722 | 723 | + Request 724 | 725 | + Headers 726 | 727 | Authorization: Bearer {access_token} 728 | 729 | + Parameters 730 | 731 | + vehicle_id: `1` (number) - The id of the Vehicle. 732 | 733 | + Response 200 (application/json) 734 | 735 | + Body 736 | 737 | { 738 | "response": { 739 | "result": true, 740 | "reason": "" 741 | } 742 | } 743 | 744 | ## Media play previous favorite [POST /api/1/vehicles/{vehicle_id}/command/media_prev_fav] 745 | 746 | Play the previous favorite 747 | 748 | + Request 749 | 750 | + Headers 751 | 752 | Authorization: Bearer {access_token} 753 | 754 | + Parameters 755 | 756 | + vehicle_id: `1` (number) - The id of the Vehicle. 757 | 758 | + Response 200 (application/json) 759 | 760 | + Body 761 | 762 | { 763 | "response": { 764 | "result": true, 765 | "reason": "" 766 | } 767 | } 768 | 769 | ## Media volume up [POST /api/1/vehicles/{vehicle_id}/command/media_volume_up] 770 | 771 | Increase media volume 772 | 773 | + Request 774 | 775 | + Headers 776 | 777 | Authorization: Bearer {access_token} 778 | 779 | + Parameters 780 | 781 | + vehicle_id: `1` (number) - The id of the Vehicle. 782 | 783 | + Response 200 (application/json) 784 | 785 | + Body 786 | 787 | { 788 | "response": { 789 | "result": true, 790 | "reason": "" 791 | } 792 | } 793 | 794 | ## Media volume down [POST /api/1/vehicles/{vehicle_id}/command/media_volume_down] 795 | 796 | Decrease media volume 797 | 798 | + Request 799 | 800 | + Headers 801 | 802 | Authorization: Bearer {access_token} 803 | 804 | + Parameters 805 | 806 | + vehicle_id: `1` (number) - The id of the Vehicle. 807 | 808 | + Response 200 (application/json) 809 | 810 | + Body 811 | 812 | { 813 | "response": { 814 | "result": true, 815 | "reason": "" 816 | } 817 | } 818 | 819 | ## Speed limit activate [POST /api/1/vehicles/{vehicle_id}/command/speed_limit_activate?pin={pin}] 820 | 821 | Activate speed limitation 822 | 823 | + Request 824 | 825 | + Headers 826 | 827 | Authorization: Bearer {access_token} 828 | 829 | + Parameters 830 | 831 | + vehicle_id: `1` (number) - The id of the Vehicle. 832 | + pin: '1234' (string) - The pin code. 833 | 834 | + Response 200 (application/json) 835 | 836 | + Body 837 | 838 | { 839 | "response": { 840 | "result": true, 841 | "reason": "" 842 | } 843 | } 844 | 845 | ## Speed limit deactivate [POST /api/1/vehicles/{vehicle_id}/command/speed_limit_deactivate?pin={pin}] 846 | 847 | Deactivate speed limitation 848 | 849 | + Request 850 | 851 | + Headers 852 | 853 | Authorization: Bearer {access_token} 854 | 855 | + Parameters 856 | 857 | + vehicle_id: `1` (number) - The id of the Vehicle. 858 | + pin: '1234' (string) - The pin code. 859 | 860 | + Response 200 (application/json) 861 | 862 | + Body 863 | 864 | { 865 | "response": { 866 | "result": true, 867 | "reason": "" 868 | } 869 | } 870 | 871 | ## Speed limit clear pin [POST /api/1/vehicles/{vehicle_id}/command/speed_limit_clear_pin?pin={pin}] 872 | 873 | Clear speed limitation pin 874 | 875 | + Request 876 | 877 | + Headers 878 | 879 | Authorization: Bearer {access_token} 880 | 881 | + Parameters 882 | 883 | + vehicle_id: `1` (number) - The id of the Vehicle. 884 | + pin: '1234' (string) - The pin code. 885 | 886 | + Response 200 (application/json) 887 | 888 | + Body 889 | 890 | { 891 | "response": { 892 | "result": true, 893 | "reason": "" 894 | } 895 | } 896 | 897 | ## Speed limit set limit [POST /api/1/vehicles/{vehicle_id}/command/speed_limit_set_limit?limit_mph={limit_mph}] 898 | 899 | Set speed limit 900 | 901 | + Request 902 | 903 | + Headers 904 | 905 | Authorization: Bearer {access_token} 906 | 907 | + Parameters 908 | 909 | + vehicle_id: `1` (number) - The id of the Vehicle. 910 | + limit_mph: '80.0' (number) - The speed limit. 911 | 912 | + Response 200 (application/json) 913 | 914 | + Body 915 | 916 | { 917 | "response": { 918 | "result": true, 919 | "reason": "" 920 | } 921 | } 922 | 923 | ## Sentry mode [POST /api/1/vehicles/{vehicle_id}/command/set_sentry_mode?on={onoff}] 924 | 925 | Enable or disable sentry mode. 926 | 927 | + Request 928 | 929 | + Headers 930 | 931 | Authorization: Bearer {access_token} 932 | 933 | + Parameters 934 | 935 | + vehicle_id: `1` (number) - The id of the Vehicle. 936 | + onoff: true (boolean) - Sentry mode state. 937 | 938 | + Response 200 (application/json) 939 | 940 | + Body 941 | 942 | { 943 | "response": { 944 | "result": true, 945 | "reason": "" 946 | } 947 | } 948 | 949 | ## Nearby chargers request [GET /api/1/vehicles/{vehicle_id}/nearby_charging_sites] 950 | 951 | Return a list of nearby Destination and Superchargers 952 | 953 | + Request 954 | 955 | + Headers 956 | 957 | Authorization: Bearer {access_token} 958 | 959 | + Parameters 960 | 961 | + vehicle_id: `1` (number) - The id of the Vehicle. 962 | 963 | + Response 200 (application/json) 964 | 965 | + Body 966 | 967 | { 968 | "response": { 969 | "congestion_sync_time_utc_secs": 1547415712, 970 | "destination_charging": [ 971 | {"location": {"lat":47.671225,"long":-122.122192},"name":"Seattle Marriott","type":"destination","distance_miles":21.744819} 972 | ], 973 | "superchargers":[ 974 | {"location":{"lat":47.671225,"long":-122.122192},"name":"Seattle, WA","type":"supercharger","distance_miles":21.345058,"available_stalls":2,"total_stalls":8,"site_closed":false} 975 | ] 976 | } 977 | } 978 | 979 | ## Seat heater request [POST /api/1/vehicles/{vehicle_id}/command/remote_seat_heater_request?heater={heater}&level={level}] 980 | 981 | Adjust seat heater levels 982 | 983 | + Request 984 | 985 | + Headers 986 | 987 | Authorization: Bearer {access_token} 988 | 989 | + Parameters 990 | 991 | + vehicle_id: `1` (number) - The id of the Vehicle. 992 | + heater: '0' (number) - The heater to adjust. 993 | + level: '1' (number) - The heater level. 994 | 995 | + Response 200 (application/json) 996 | 997 | + Body 998 | 999 | { 1000 | "response": { 1001 | "result": true, 1002 | "reason": "" 1003 | } 1004 | } 1005 | 1006 | ## Window control request [POST /api/1/vehicles/{vehicle_id}/command/window_control?command={command}] 1007 | 1008 | Control the windows 1009 | 1010 | + Request 1011 | 1012 | + Headers 1013 | 1014 | Authorization: Bearer {access_token} 1015 | 1016 | + Parameters 1017 | 1018 | + vehicle_id: `1` (number) - The id of the Vehicle. 1019 | + command: 'open' (string) - Action to take. Allowable values are 'vent' and 'close' 1020 | 1021 | + Response 200 (application/json) 1022 | 1023 | + Body 1024 | 1025 | { 1026 | "response": { 1027 | "result": true, 1028 | "reason": "" 1029 | } 1030 | } 1031 | 1032 | ## Max Defrost request [POST /api/1/vehicles/{vehicle_id}/command/set_preconditioning_max?command={command}] 1033 | 1034 | Toggles the climate controls between Max Defrost and the previous setting 1035 | 1036 | + Request 1037 | 1038 | + Headers 1039 | 1040 | Authorization: Bearer {access_token} 1041 | 1042 | + Parameters 1043 | 1044 | + vehicle_id: `1` (number) - The id of the Vehicle. 1045 | + command: true (boolean) - Action to take. True to turn on, false to turn off. 1046 | 1047 | + Response 200 (application/json) 1048 | 1049 | + Body 1050 | 1051 | { 1052 | "response": { 1053 | "result": true, 1054 | "reason": "" 1055 | } 1056 | } 1057 | 1058 | ## Steering heater request [POST /api/1/vehicles/{vehicle_id}/command/remote_steering_wheel_heater_request?on={on}] 1059 | 1060 | Adjust steering heater levels 1061 | 1062 | + Request 1063 | 1064 | + Headers 1065 | 1066 | Authorization: Bearer {access_token} 1067 | 1068 | + Parameters 1069 | 1070 | + vehicle_id: `1` (number) - The id of the Vehicle. 1071 | + on: '1' (number) - The heater level. 1072 | 1073 | + Response 200 (application/json) 1074 | 1075 | + Body 1076 | 1077 | { 1078 | "response": { 1079 | "result": true, 1080 | "reason": "" 1081 | } 1082 | } 1083 | 1084 | ## Navigation Request [POST /api/1/vehicles/{vehicle_id}/command/navigation_request?subject={subject}&text={text}&locale={locale}] 1085 | 1086 | Sends a navigation request to the car 1087 | 1088 | + Request 1089 | 1090 | + Headers 1091 | 1092 | Authorization: Bearer {access_token} 1093 | 1094 | + Parameters 1095 | 1096 | + vehicle_id: `1` (number) - The id of the Vehicle. 1097 | + subject: `Tesla` (string) - Short name of location. 1098 | + text: `Tesla Motors Corporation Freemont, CA` (string) - The name, address and map location of destination. 1099 | + locale: `en-US` (string) - The locale. 1100 | 1101 | + Response 200 (application/json) 1102 | 1103 | + Body 1104 | 1105 | { 1106 | "response": { 1107 | "result": true, 1108 | "reason": "" 1109 | } 1110 | } 1111 | 1112 | ## Set Valet Mode [POST /api/1/vehicles/{vehicle_id}/command/set_valet_mode?on={on}&password={password}] 1113 | 1114 | Sets valet mode on or off with a PIN to disable it from within the car. Reuses last PIN from previous valet session. 1115 | 1116 | Valet Mode limits the car's top speed to 70MPH and 80kW of acceleration power. It also disables Homelink, Bluetooth and 1117 | 1118 | Wifi settings, and the ability to disable mobile access to the car. It also hides your favorites, home, and work 1119 | 1120 | locations in navigation. 1121 | 1122 | 1123 | 1124 | + Request 1125 | 1126 | + Headers 1127 | 1128 | Authorization: Bearer {access_token} 1129 | 1130 | + Parameters 1131 | 1132 | + vehicle_id: `1` (number) - The id of the Vehicle. 1133 | + on: true (boolean) - Whether to enable or disable valet mode. 1134 | + password: 1234 (number) - (optional) A 4 digit PIN code to unlock the car. 1135 | 1136 | + Response 200 (application/json) 1137 | 1138 | + Body 1139 | 1140 | { 1141 | "response": { 1142 | "result": true, 1143 | "reason": "" 1144 | } 1145 | } 1146 | 1147 | ## Reset Valet PIN [POST /api/1/vehicles/{vehicle_id}/command/reset_valet_pin] 1148 | 1149 | Resets the PIN set for valet mode, if set. 1150 | 1151 | + Request 1152 | 1153 | + Headers 1154 | 1155 | Authorization: Bearer {access_token} 1156 | 1157 | + Parameters 1158 | 1159 | + vehicle_id: `1` (number) - The id of the Vehicle. 1160 | 1161 | + Response 200 (application/json) 1162 | 1163 | + Body 1164 | 1165 | { 1166 | "response": { 1167 | "result": true, 1168 | "reason": "" 1169 | } 1170 | } 1171 | 1172 | ## Open Charge Port [POST /api/1/vehicles/{vehicle_id}/command/charge_port_door_open] 1173 | 1174 | Opens the charge port. 1175 | 1176 | + Request 1177 | 1178 | + Headers 1179 | 1180 | Authorization: Bearer {access_token} 1181 | 1182 | + Parameters 1183 | 1184 | + vehicle_id: `1` (number) - The id of the Vehicle. 1185 | 1186 | + Response 200 (application/json) 1187 | 1188 | + Body 1189 | 1190 | { 1191 | "response": { 1192 | "result": true, 1193 | "reason": "" 1194 | } 1195 | } 1196 | 1197 | ## Close Charge Port [POST /api/1/vehicles/{vehicle_id}/command/charge_port_door_close] 1198 | 1199 | Closes the charge port. 1200 | 1201 | + Request 1202 | 1203 | + Headers 1204 | 1205 | Authorization: Bearer {access_token} 1206 | 1207 | + Parameters 1208 | 1209 | + vehicle_id: `1` (number) - The id of the Vehicle. 1210 | 1211 | + Response 200 (application/json) 1212 | 1213 | + Body 1214 | 1215 | { 1216 | "response": { 1217 | "result": true, 1218 | "reason": "" 1219 | } 1220 | } 1221 | ## Set Charge Limit to Standard [POST /api/1/vehicles/{vehicle_id}/command/charge_standard] 1222 | 1223 | Set the charge mode to standard (90% under the new percentage system introduced in 4.5). 1224 | 1225 | + Request 1226 | 1227 | + Headers 1228 | 1229 | Authorization: Bearer {access_token} 1230 | 1231 | + Parameters 1232 | 1233 | + vehicle_id: `1` (number) - The id of the Vehicle. 1234 | 1235 | + Response 200 (application/json) 1236 | 1237 | + Body 1238 | 1239 | { 1240 | "response": { 1241 | "result": true, 1242 | "reason": "" 1243 | } 1244 | } 1245 | 1246 | ## Set Charge Limit to Max Range [POST /api/1/vehicles/{vehicle_id}/command/charge_max_range] 1247 | 1248 | Set the charge mode to max range (100% under the new percentage system introduced in 4.5). Use sparingly! 1249 | 1250 | + Request 1251 | 1252 | + Headers 1253 | 1254 | Authorization: Bearer {access_token} 1255 | 1256 | + Parameters 1257 | 1258 | + vehicle_id: `1` (number) - The id of the Vehicle. 1259 | 1260 | + Response 200 (application/json) 1261 | 1262 | + Body 1263 | 1264 | { 1265 | "response": { 1266 | "result": true, 1267 | "reason": "" 1268 | } 1269 | } 1270 | 1271 | ## Set Charge Limit [POST /api/1/vehicles/{vehicle_id}/command/set_charge_limit?percent={limit_value}] 1272 | 1273 | Set the charge limit to a custom percentage. 1274 | 1275 | + Request 1276 | 1277 | + Headers 1278 | 1279 | Authorization: Bearer {access_token} 1280 | 1281 | + Parameters 1282 | 1283 | + vehicle_id: `1` (number) - The id of the Vehicle. 1284 | + limit_value: `75` (number) - The percentage value 1285 | 1286 | + Response 200 (application/json) 1287 | 1288 | + Body 1289 | 1290 | { 1291 | "response": { 1292 | "result": true, 1293 | "reason": "" 1294 | } 1295 | } 1296 | 1297 | ## Start Charging [POST /api/1/vehicles/{vehicle_id}/command/charge_start] 1298 | 1299 | Start charging. Must be plugged in, have power available, and not have reached your charge limit. 1300 | 1301 | + Request 1302 | 1303 | + Headers 1304 | 1305 | Authorization: Bearer {access_token} 1306 | 1307 | + Parameters 1308 | 1309 | + vehicle_id: `1` (number) - The id of the Vehicle. 1310 | 1311 | + Response 200 (application/json) 1312 | 1313 | + Body 1314 | 1315 | { 1316 | "response": { 1317 | "result": true, 1318 | "reason": "" 1319 | } 1320 | } 1321 | 1322 | ## Stop Charging [POST /api/1/vehicles/{vehicle_id}/command/charge_stop] 1323 | 1324 | Stop charging. Must already be charging. 1325 | 1326 | + Request 1327 | 1328 | + Headers 1329 | 1330 | Authorization: Bearer {access_token} 1331 | 1332 | + Parameters 1333 | 1334 | + vehicle_id: `1` (number) - The id of the Vehicle. 1335 | 1336 | + Response 200 (application/json) 1337 | 1338 | + Body 1339 | 1340 | { 1341 | "response": { 1342 | "result": true, 1343 | "reason": "" 1344 | } 1345 | } 1346 | 1347 | ## Flash Lights [POST /api/1/vehicles/{vehicle_id}/command/flash_lights] 1348 | 1349 | Flash the lights once. 1350 | 1351 | + Request 1352 | 1353 | + Headers 1354 | 1355 | Authorization: Bearer {access_token} 1356 | 1357 | + Parameters 1358 | 1359 | + vehicle_id: `1` (number) - The id of the Vehicle. 1360 | 1361 | + Response 200 (application/json) 1362 | 1363 | + Body 1364 | 1365 | { 1366 | "response": { 1367 | "result": true, 1368 | "reason": "" 1369 | } 1370 | } 1371 | 1372 | ## Honk Horn [POST /api/1/vehicles/{vehicle_id}/command/honk_horn] 1373 | 1374 | Honk the horn once. 1375 | 1376 | + Request 1377 | 1378 | + Headers 1379 | 1380 | Authorization: Bearer {access_token} 1381 | 1382 | + Parameters 1383 | 1384 | + vehicle_id: `1` (number) - The id of the Vehicle. 1385 | 1386 | + Response 200 (application/json) 1387 | 1388 | + Body 1389 | 1390 | { 1391 | "response": { 1392 | "result": true, 1393 | "reason": "" 1394 | } 1395 | } 1396 | 1397 | ## Unlock Doors [POST /api/1/vehicles/{vehicle_id}/command/door_unlock] 1398 | 1399 | Unlock the car's doors. 1400 | 1401 | + Request 1402 | 1403 | + Headers 1404 | 1405 | Authorization: Bearer {access_token} 1406 | 1407 | + Parameters 1408 | 1409 | + vehicle_id: `1` (number) - The id of the Vehicle. 1410 | 1411 | + Response 200 (application/json) 1412 | 1413 | + Body 1414 | 1415 | { 1416 | "response": { 1417 | "result": true, 1418 | "reason": "" 1419 | } 1420 | } 1421 | 1422 | ## Lock Doors [POST /api/1/vehicles/{vehicle_id}/command/door_lock] 1423 | 1424 | Lock the car's doors. 1425 | 1426 | + Request 1427 | 1428 | + Headers 1429 | 1430 | Authorization: Bearer {access_token} 1431 | 1432 | + Parameters 1433 | 1434 | + vehicle_id: `1` (number) - The id of the Vehicle. 1435 | 1436 | + Response 200 (application/json) 1437 | 1438 | + Body 1439 | 1440 | { 1441 | "response": { 1442 | "result": true, 1443 | "reason": "" 1444 | } 1445 | } 1446 | 1447 | ## Set Temperature [POST /api/1/vehicles/{vehicle_id}/command/set_temps?driver_temp={driver_degC}&passenger_temp={pass_degC}] 1448 | 1449 | Set the temperature target for the HVAC system. 1450 | 1451 | + Request 1452 | 1453 | + Headers 1454 | 1455 | Authorization: Bearer {access_token} 1456 | 1457 | + Parameters 1458 | 1459 | + vehicle_id: `1` (number) - The id of the Vehicle. 1460 | + driver_degC: `23.7` (number) - The desired temperature on the driver's side in celcius. 1461 | + pass_degC: `18.1` (number) - The desired temperature on the passenger's side in celcius. 1462 | 1463 | + Response 200 (application/json) 1464 | 1465 | + Body 1466 | 1467 | { 1468 | "response": { 1469 | "result": true, 1470 | "reason": "" 1471 | } 1472 | } 1473 | 1474 | ## Start HVAC System [POST /api/1/vehicles/{vehicle_id}/command/auto_conditioning_start] 1475 | 1476 | Start the climate control system. Will cool or heat automatically, depending on set temperature. 1477 | 1478 | + Request 1479 | 1480 | + Headers 1481 | 1482 | Authorization: Bearer {access_token} 1483 | 1484 | + Parameters 1485 | 1486 | + vehicle_id: `1` (number) - The id of the Vehicle. 1487 | 1488 | + Response 200 (application/json) 1489 | 1490 | + Body 1491 | 1492 | { 1493 | "response": { 1494 | "result": true, 1495 | "reason": "" 1496 | } 1497 | } 1498 | 1499 | ## Stop HVAC System [POST /api/1/vehicles/{vehicle_id}/command/auto_conditioning_stop] 1500 | 1501 | Stop the climate control system. 1502 | 1503 | + Request 1504 | 1505 | + Headers 1506 | 1507 | Authorization: Bearer {access_token} 1508 | 1509 | + Parameters 1510 | 1511 | + vehicle_id: `1` (number) - The id of the Vehicle. 1512 | 1513 | + Response 200 (application/json) 1514 | 1515 | + Body 1516 | 1517 | { 1518 | "response": { 1519 | "result": true, 1520 | "reason": "" 1521 | } 1522 | } 1523 | 1524 | ## Move Pano Roof [POST /api/1/vehicles/{vehicle_id}/command/sun_roof_control?state={state}&percent={percent}] 1525 | 1526 | Controls the car's panoramic roof, if installed. 1527 | 1528 | + Request 1529 | 1530 | + Headers 1531 | 1532 | Authorization: Bearer {access_token} 1533 | 1534 | + Parameters 1535 | 1536 | + vehicle_id: `1` (number) - The id of the Vehicle. 1537 | + state: `open` (enum[string]) 1538 | The desired state of the panoramic roof. The approximate percent open values for each state are `open` = 100%, `close` = 0%, `comfort` = 80%, and `vent` = ~15% 1539 | + Members 1540 | + `open` - Open the roof fully 1541 | + `close` - Close the roof completely 1542 | + `comfort` - Open to the comfort (80%) setting 1543 | + `vent` - Open the roof to the vent (~15%) setting 1544 | + `move` - Indicates you will provide a percentage to move the roof. 1545 | + percent: `50` (number, optional) - The percentage to move the roof to. 1546 | 1547 | + Response 200 (application/json) 1548 | 1549 | + Body 1550 | 1551 | { 1552 | "response": { 1553 | "result": true, 1554 | "reason": "" 1555 | } 1556 | } 1557 | 1558 | ## Remote Start [POST /api/1/vehicles/{vehicle_id}/command/remote_start_drive?password={password}] 1559 | 1560 | Start the car for keyless driving. Must start driving within 2 minutes of issuing this request. 1561 | 1562 | + Request 1563 | 1564 | + Headers 1565 | 1566 | Authorization: Bearer {access_token} 1567 | 1568 | + Parameters 1569 | 1570 | + vehicle_id: `1` (number) - The id of the Vehicle. 1571 | + password: `edisonsux` (string) - The password to the authenticated my.teslamotors.com account. 1572 | 1573 | + Response 200 (application/json) 1574 | 1575 | + Body 1576 | 1577 | { 1578 | "response": { 1579 | "result": true, 1580 | "reason": "" 1581 | } 1582 | } 1583 | 1584 | ## Open Trunk/Frunk [POST /api/1/vehicles/{vehicle_id}/command/actuate_trunk?which_trunk={which_trunk}] 1585 | 1586 | Open the trunk or frunk. Currently inoperable. 1587 | 1588 | + Request 1589 | 1590 | + Headers 1591 | 1592 | Authorization: Bearer {access_token} 1593 | 1594 | + Parameters 1595 | 1596 | + vehicle_id: `1` (number) - The id of the Vehicle. 1597 | + which_trunk: `rear` (string) - The trunk to open. `rear` is the only one known currently. 1598 | 1599 | + Response 200 (application/json) 1600 | 1601 | + Body 1602 | 1603 | { 1604 | "response": { 1605 | "result": true, 1606 | "reason": "" 1607 | } 1608 | } 1609 | 1610 | ## Trigger Homelink [POST /api/1/vehicles/{vehicle_id}/command/trigger_homelink?lat={lat}&long={long}&token={token}] 1611 | 1612 | Trigger homelink. 1613 | 1614 | + Request 1615 | 1616 | + Headers 1617 | 1618 | Authorization: Bearer {access_token} 1619 | 1620 | + Parameters 1621 | 1622 | + vehicle_id: `1` (number) - The id of the Vehicle. 1623 | + lat: `75` (number) - The home latitude. 1624 | + long: `34` (number) - The home longitude. 1625 | + token: `75` (string) - The streaming token. 1626 | 1627 | + Response 200 (application/json) 1628 | 1629 | + Body 1630 | 1631 | { 1632 | "response": { 1633 | "result": true, 1634 | "reason": "" 1635 | } 1636 | } 1637 | 1638 | ## Update Calendar [POST /api/1/vehicles/{vehicle_id}/command/upcoming_calendar_entries] 1639 | 1640 | Update calendar. 1641 | 1642 | + Request 1643 | 1644 | + Headers 1645 | 1646 | Authorization: Bearer {access_token} 1647 | 1648 | + Response 200 (application/json) 1649 | 1650 | + Body 1651 | 1652 | { 1653 | "response": { 1654 | "result": true, 1655 | "reason": "" 1656 | } 1657 | } 1658 | 1659 | 1660 | ## Bad Get [GET /api/1/vehicles/{vehicle_id}/data_request/err_get] 1661 | 1662 | This is a GET that is guaranteed to fail. 1663 | 1664 | + Request 1665 | 1666 | + Headers 1667 | 1668 | Authorization: Bearer {access_token} 1669 | 1670 | + Response 400 (text/xml) 1671 | 1672 | + Body 1673 | 1674 | Unknown Request 1675 | 1676 | ## Bad Post [POST /api/1/vehicles/{vehicle_id}/command/err_post] 1677 | 1678 | This is a POST that is guaranteed to fail. 1679 | 1680 | + Parameters 1681 | 1682 | + vehicle_id: `1` (number) - The id of the Vehicle. 1683 | 1684 | + Request 1685 | 1686 | + Headers 1687 | 1688 | Authorization: Bearer {access_token} 1689 | 1690 | + Response 400 (text/xml) 1691 | 1692 | + Body 1693 | 1694 | Unknown Request 1695 | 1696 | ## Streaming [GET /{vehicle_id}/?values=elevation,est_heading,est_lat,est_lng,est_range,heading,odometer,power,range,shift_state,speed,soc] 1697 | 1698 | This models the streaming API interface. 1699 | 1700 | + Parameters 1701 | 1702 | + vehicle_id: `1` (number) - The id of the Vehicle. 1703 | 1704 | + Request 1705 | 1706 | + Headers 1707 | 1708 | Authorization: Bearer {access_token} 1709 | 1710 | + Response 200 (application/json) 1711 | 1712 | + Body 1713 | 1714 | { 1715 | "result": "['elevation', 'est_heading', 'est_lat', 'est_lng', 'est_range', 'heading', 'odometer', 'power', 'range', 'shift_state', 'speed', 'soc']" 1716 | } 1717 | 1718 | ## Get Owned Tesla Product List [GET /api/1/products] 1719 | 1720 | Get a list of the users owned Tesla products. 1721 | 1722 | + Request 1723 | 1724 | + Headers 1725 | 1726 | Authorization: Bearer {access_token} 1727 | 1728 | + Response 200 (application/json) 1729 | 1730 | + Body 1731 | 1732 | { 1733 | "response": [{ 1734 | "id": 1 1735 | }] 1736 | } 1737 | 1738 | ## Get Current Solar Usage [GET /api/1/energy_sites/{site_id}/live_status] 1739 | 1740 | Get solar live status. 1741 | 1742 | + Request 1743 | 1744 | + Headers 1745 | 1746 | Authorization: Bearer {access_token} 1747 | 1748 | + Parameters 1749 | 1750 | + site_id: `1` (number) - The id of the Vehicle. 1751 | 1752 | + Response 200 (application/json) 1753 | 1754 | + Body 1755 | 1756 | { 1757 | "response": { 1758 | "solar_power": 1000, 1759 | "load_power": 750, 1760 | "grid_power": 250 1761 | } 1762 | } --------------------------------------------------------------------------------