forked from mseminatore/TeslaJS
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathteslajs.min.js
15 lines (15 loc) · 18.4 KB
/
teslajs.min.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* @file This is a Node.js module encapsulating the unofficial Tesla API set
*
* Github: https://github.com/mseminatore/TeslaJS
* NPM: https://www.npmjs.com/package/teslajs
*
* @copyright Copyright (c) 2016 Mark Seminatore
*
* @license MIT
*
* Refer to included LICENSE file for usage rights and restrictions
*/
"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/",streamingBaseURI=(exports.streamingPortal=streamingPortal,process.env.TESLAJS_STREAMING??streamingPortal),portal="https://owner-api.teslamotors.com",portalBaseURI=(exports.portal=portal,process.env.TESLAJS_SERVER??portal),API_LOG_ALWAYS=0,API_ERR_LEVEL=(exports.API_LOG_ALWAYS=API_LOG_ALWAYS,1),API_CALL_LEVEL=(exports.API_ERR_LEVEL=API_ERR_LEVEL,2),API_RETURN_LEVEL=(exports.API_CALL_LEVEL=API_CALL_LEVEL,3),API_BODY_LEVEL=(exports.API_RETURN_LEVEL=API_RETURN_LEVEL,4),API_REQUEST_LEVEL=(exports.API_BODY_LEVEL=API_BODY_LEVEL,5),API_RESPONSE_LEVEL=(exports.API_REQUEST_LEVEL=API_REQUEST_LEVEL,6),API_LOG_ALL=(exports.API_RESPONSE_LEVEL=API_RESPONSE_LEVEL,255),logLevel=(exports.API_LOG_ALL=API_LOG_ALL,process.env.TESLAJS_LOG??0);function log(e,o){logLevel<e||console.log(o)}function clamp(e,o,t){return e=t<(e=e<o?o:e)?t:e}function get_command(e,o,t,n){exports.get(e,`/api/1/vehicles/${e.vehicleID}/`+o,t,n)}function post_command(e,o,t,n,s){exports.post(e,`/api/1/vehicles/${e.vehicleID}/`+o,t,n,s)}exports.setLogLevel=function(e){logLevel=e},exports.getLogLevel=function(){return logLevel},exports.setPortalBaseURI=function(e){portalBaseURI=e||portal},exports.getPortalBaseURI=function(){return portalBaseURI},exports.setStreamingBaseURI=function(e){streamingBaseURI=e||streamingPortal},exports.getStreamingBaseURI=function(){return streamingBaseURI},exports.getModel=function(e){return exports.vinDecode(e).carType},exports.vinDecode=function(e){var o={carType:"Model S",awd:!1,year:2012};if(e&&e.vin){var t=e.vin.charCodeAt(9);switch(o.year=2010+t-"A".charCodeAt(0),73<t&&o.year--,e.vin.charAt(3)){case"S":o.carType="Model S";break;case"3":o.carType="Model 3";break;case"X":o.carType="Model X";break;case"Y":o.carType="Model Y";break;case"R":o.carType="Roadster"}"2"!=e.vin.charAt(7)&&"4"!=e.vin.charAt(7)&&"B"!=e.vin.charAt(7)&&"C"!=e.vin.charAt(7)&&"E"!=e.vin.charAt(7)||(o.awd=!0)}return o},exports.getPaintColor=function(e){return{PBCW:"white",PBSB:"black",PMAB:"metallic brown",PMBL:"metallic black",PMMB:"metallic blue",PMMR:"multi-coat red",PPMR:"multi-coat red",PMNG:"steel grey",PMSG:"metallic green",PMSS:"metallic silver",PPSB:"ocean blue",PPSR:"signature red",PPSW:"pearl white",PPTI:"titanium",PMTG:"metallic grey"}[e.option_codes.match(/PBCW|PBSB|PMAB|PMBL|PMMB|PMMR|PPMR|PMNG|PMSG|PMSS|PPSB|PPSR|PPSW|PPTI|PMTG/)]??"black"},exports.getVin=function(e){if(e&&e.vin)return e.vin;throw new Error("invalid parameter")},exports.getShortVin=function(e){if(e&&e.vin)return e.vin.substr(11);throw new Error("invalid parameter")},exports.login=function(e,s){log(API_CALL_LEVEL,"TeslaJS.login()"),"string"==typeof arguments[0]&&"string"==typeof arguments[1]&&(e={username:arguments[0],password:arguments[1]},s=arguments[2]),s=s??function(e,o){},(e=e??{}).username&&e.password?require("./src/auth").login({identity:e.username,credential:e.password,mfaPassCode:e.mfaPassCode,mfaDeviceName:e.mfaDeviceName},function(e,o,t){log(API_RESPONSE_LEVEL,"\nResponse: "+JSON.stringify(o)),log(API_RESPONSE_LEVEL,"\nBody: "+JSON.stringify(t));var n=t??{};s(e,{error:e,response:o,body:t,authToken:n.access_token,refreshToken:n.refresh_token}),log(API_RETURN_LEVEL,"TeslaJS.login() completed.")}):s("login() requires username and password",null)},exports.loginAsync=Promise.denodeify(exports.login),exports.refreshToken=function(e,n){log(API_CALL_LEVEL,"TeslaJS.refreshToken()"),n=n??function(e,o){},e?(e={method:"POST",url:portalBaseURI+"/oauth/token",body:{grant_type:"refresh_token",refresh_token:e}},log(API_REQUEST_LEVEL,"\nRequest: "+JSON.stringify(e)),request(e,function(e,o,t){log(API_RESPONSE_LEVEL,"\nResponse: "+t),n(e,{error:e,response:o,body:JSON.stringify(t),authToken:t.access_token,refreshToken:t.refresh_token}),log(API_RETURN_LEVEL,"TeslaJS.refreshToken() completed.")})):n("refreshToken() requires a refresh_token",null)},exports.refreshTokenAsync=Promise.denodeify(exports.refreshToken),exports.logout=function(e,n){log(API_CALL_LEVEL,"TeslaJS.logout()"),n=n??function(e,o){},request({headers:{Authorization:"Bearer "+e,"Content-Type":"application/json; charset=utf-8"},method:"POST",url:portalBaseURI+"/oauth/revoke"},function(e,o,t){n(e,{error:e,response:o,body:JSON.stringify(t)}),log(API_RETURN_LEVEL,"TeslaJS.logout() completed.")})},exports.logoutAsync=Promise.denodeify(exports.logout),exports.get=function(e,n,o,s){log(API_CALL_LEVEL,"TeslaJS.get()"),s=s??function(e,o){};e={headers:{Authorization:"Bearer "+e.authToken,"Content-Type":"application/json; charset=utf-8"},method:"GET",url:portalBaseURI+n,qs:o};log(API_REQUEST_LEVEL,"\nRequest: "+JSON.stringify(e)),request(e,function(e,o,t){if(e)return log(API_ERR_LEVEL,e),s(e,null);if(200!=o.statusCode)return s(o.statusMessage,null);log(API_BODY_LEVEL,"\nBody: "+JSON.stringify(t)),log(API_RESPONSE_LEVEL,"\nResponse: "+JSON.stringify(o));try{t=t.response,s(null,t)}catch(e){log(API_ERR_LEVEL,`Error parsing ${n} response`),s(e,null)}log(API_RETURN_LEVEL,`
GET request: ${n} completed.`)})},exports.getAsync=Promise.denodeify(exports.get),exports.post=function(e,n,o,t,s){log(API_CALL_LEVEL,"TeslaJS.post()"),s=s??function(e,o){};e={headers:{Authorization:"Bearer "+e.authToken,"Content-Type":"application/json; charset=utf-8"},method:"POST",url:portalBaseURI+n,qs:o,body:t};log(API_REQUEST_LEVEL,"\nRequest: "+JSON.stringify(e)),request(e,function(e,o,t){if(e)return log(API_ERR_LEVEL,e),s(e,null);if(200!=o.statusCode)return s(o.statusMessage,null);log(API_BODY_LEVEL,"\nBody: "+JSON.stringify(t)),log(API_RESPONSE_LEVEL,"\nResponse: "+JSON.stringify(o));try{t=t.response,s(null,t)}catch(e){log(API_ERR_LEVEL,`Error parsing ${n} response`),s(e,null)}log(API_RETURN_LEVEL,`
POST request: ${n} completed.`)})},exports.postAsync=Promise.denodeify(exports.post),exports.vehicle=function(e,n,s){s=s??function(e,o){},exports.vehicles(e,n,function(e,o){if(e)return s(e,null);try{var t=o[n?.carIndex??0];s(null,t)}catch(e){log(API_ERR_LEVEL,"Error parsing vehicles response"),s(e,null)}})},exports.vehicleAsync=Promise.denodeify(exports.vehicle),exports.vehicleById=function(e,o,t){exports.get(e,"/api/1/vehicles/"+e.vehicleID,null,t)},exports.vehicleByIdAsync=Promise.denodeify(exports.vehicleById),exports.vehicles=function(e,o,t){exports.get(e,"/api/1/vehicles",null,t)},exports.vehiclesAsync=Promise.denodeify(exports.vehicles),exports.get_command=get_command,exports.get_commandAsync=Promise.denodeify(exports.get_command),exports.post_command=post_command,exports.post_commandAsync=Promise.denodeify(exports.post_command),exports.vehicleData=function(e,o,t){var n=o?.endpoints??["climate_state","charge_state","drive_state","gui_settings","vehicle_state","vehicle_config"],o=(Array.isArray(n)&&(n=n.join(";")),o?.let_sleep);get_command(e,"vehicle_data",{endpoints:n,let_sleep:o},t)},exports.vehicleDataAsync=Promise.denodeify(exports.vehicleData),exports.vehicleConfig=function(e,o,t){get_command(e,"data_request/vehicle_config",null,t)},exports.vehicleConfigAsync=Promise.denodeify(exports.vehicleConfig),exports.vehicleState=function(e,o,t){get_command(e,"data_request/vehicle_state",null,t)},exports.vehicleStateAsync=Promise.denodeify(exports.vehicleState),exports.climateState=function(e,o,t){get_command(e,"data_request/climate_state",null,t)},exports.climateStateAsync=Promise.denodeify(exports.climateState),exports.nearbyChargers=function(e,o,t){get_command(e,"nearby_charging_sites",null,t)},exports.nearbyChargersAsync=Promise.denodeify(exports.nearbyChargers),exports.driveState=function(e,o,t){get_command(e,"data_request/drive_state",null,t)},exports.driveStateAsync=Promise.denodeify(exports.driveState),exports.chargeState=function(e,o,t){get_command(e,"data_request/charge_state",null,t)},exports.chargeStateAsync=Promise.denodeify(exports.chargeState),exports.guiSettings=function(e,o,t){get_command(e,"data_request/gui_settings",null,t)},exports.guiSettingsAsync=Promise.denodeify(exports.guiSettings),exports.mobileEnabled=function(e,o,t){get_command(e,"mobile_enabled",null,t)},exports.mobileEnabledAsync=Promise.denodeify(exports.mobileEnabled),exports.honkHorn=function(e,o,t){post_command(e,"command/honk_horn",null,null,t)},exports.honkHornAsync=Promise.denodeify(exports.honkHorn),exports.flashLights=function(e,o,t){post_command(e,"command/flash_lights",null,null,t)},exports.flashLightsAsync=Promise.denodeify(exports.flashLights),exports.startCharge=function(e,o,t){post_command(e,"command/charge_start",null,null,t)},exports.startChargeAsync=Promise.denodeify(exports.startCharge),exports.stopCharge=function(e,o,t){post_command(e,"command/charge_stop",null,null,t)},exports.stopChargeAsync=Promise.denodeify(exports.stopCharge),exports.openChargePort=function(e,o,t){post_command(e,"command/charge_port_door_open",null,null,t)},exports.openChargePortAsync=Promise.denodeify(exports.openChargePort),exports.closeChargePort=function(e,o,t){post_command(e,"command/charge_port_door_close",null,null,t)},exports.closeChargePortAsync=Promise.denodeify(exports.closeChargePort),exports.scheduleSoftwareUpdate=function(e,o,t){post_command(e,"command/schedule_software_update",null,{offset_sec:o?.offset},t)},exports.scheduleSoftwareUpdateAsync=Promise.denodeify(exports.scheduleSoftwareUpdate),exports.cancelSoftwareUpdate=function(e,o,t){post_command(e,"command/cancel_software_update",null,null,t)},exports.cancelSoftwareUpdateAsync=Promise.denodeify(exports.cancelSoftwareUpdate),exports.navigationRequest=function(e,o,t){post_command(e,"command/navigation_request",null,{type:"share_ext_content_raw",value:{"android.intent.ACTION":"android.intent.action.SEND","android.intent.TYPE":"text/plain","android.intent.extra.SUBJECT":o?.subject,"android.intent.extra.TEXT":o?.text},locale:o?.locale,timestamp_ms:Date.now()},t)},exports.navigationRequestAsync=Promise.denodeify(exports.navigationRequest),exports.mediaTogglePlayback=function(e,o,t){post_command(e,"command/media_toggle_playback",null,null,t)},exports.mediaTogglePlaybackAsync=Promise.denodeify(exports.mediaTogglePlayback),exports.mediaPlayNext=function(e,o,t){post_command(e,"command/media_next_track",null,null,t)},exports.mediaPlayNextAsync=Promise.denodeify(exports.mediaPlayNext),exports.mediaPlayPrevious=function(e,o,t){post_command(e,"command/media_prev_track",null,null,t)},exports.mediaPlayPreviousAsync=Promise.denodeify(exports.mediaPlayPrevious),exports.mediaPlayNextFavorite=function(e,o,t){post_command(e,"command/media_next_fav",null,null,t)},exports.mediaPlayNextFavoriteAsync=Promise.denodeify(exports.mediaPlayNextFavorite),exports.mediaPlayPreviousFavorite=function(e,o,t){post_command(e,"command/media_prev_fav",null,null,t)},exports.mediaPlayPreviousFavoriteAsync=Promise.denodeify(exports.mediaPlayPreviousFavorite),exports.mediaVolumeUp=function(e,o,t){post_command(e,"command/media_volume_up",null,null,t)},exports.mediaVolumeUpAsync=Promise.denodeify(exports.mediaVolumeUp),exports.mediaVolumeDown=function(e,o,t){post_command(e,"command/media_volume_down",null,null,t)},exports.mediaVolumeDownAsync=Promise.denodeify(exports.mediaVolumeDown),exports.speedLimitActivate=function(e,o,t){post_command(e,"command/speed_limit_activate",null,o,t)},exports.speedLimitActivateAsync=Promise.denodeify(exports.speedLimitActivate),exports.speedLimitDeactivate=function(e,o,t){post_command(e,"command/speed_limit_deactivate",null,o,t)},exports.speedLimitDeactivateAsync=Promise.denodeify(exports.speedLimitDeactivate),exports.speedLimitClearPin=function(e,o,t){post_command(e,"command/speed_limit_clear_pin",null,o,t)},exports.speedLimitClearPinAsync=Promise.denodeify(exports.speedLimitClearPin),exports.speedLimitSetLimit=function(e,o,t){post_command(e,"command/speed_limit_set_limit",null,{limit_mph:o?.limit},t)},exports.speedLimitSetLimitAsync=Promise.denodeify(exports.speedLimitSetLimit),exports.setSentryMode=function(e,o,t){post_command(e,"command/set_sentry_mode",null,{on:o?.onoff},t)},exports.setSentryModeAsync=Promise.denodeify(exports.setSentryMode),exports.seatHeater=function(e,o,t){post_command(e,"command/remote_seat_heater_request",null,o,t)},exports.seatHeaterAsync=Promise.denodeify(exports.seatHeater),exports.steeringHeater=function(e,o,t){post_command(e,"command/remote_steering_wheel_heater_request",null,{on:o?.level},t)},exports.steeringHeaterAsync=Promise.denodeify(exports.steeringHeater),exports.maxDefrost=function(e,o,t){post_command(e,"command/set_preconditioning_max",null,{on:o?.onoff},t)},exports.maxDefrostAsync=Promise.denodeify(exports.maxDefrost),exports.windowControl=function(e,o,t){post_command(e,"command/window_control",null,{command:o?.command,lat:o?.lat??0,lon:o?.lon??0},t)},exports.windowControlAsync=Promise.denodeify(exports.windowControl),exports.CHARGE_STORAGE=50,exports.CHARGE_DAILY=70,exports.CHARGE_STANDARD=90,exports.CHARGE_RANGE=100,exports.setChargeLimit=function(e,o,t){post_command(e,"command/set_charge_limit",null,{percent:clamp(o?.amt??exports.CHARGE_DAILY,exports.CHARGE_STORAGE,exports.CHARGE_RANGE)},t)},exports.setChargeLimitAsync=Promise.denodeify(exports.setChargeLimit),exports.chargeStandard=function(e,o,t){post_command(e,"command/charge_standard",null,null,t)},exports.chargeStandardAsync=Promise.denodeify(exports.chargeStandard),exports.chargeMaxRange=function(e,o,t){post_command(e,"command/charge_max_range",null,null,t)},exports.chargeMaxRangeAsync=Promise.denodeify(exports.chargeMaxRange),exports.setChargingAmps=function(e,o,t){post_command(e,"command/set_charging_amps",null,{charging_amps:o?.amps},t)},exports.setChargingAmpsAsync=Promise.denodeify(exports.setChargingAmps),exports.setScheduledCharging=function(e,o,t){post_command(e,"command/set_scheduled_charging",null,o,t)},exports.setScheduledChargingAsync=Promise.denodeify(exports.setScheduledCharging),exports.setScheduledDeparture=function(e,o,t){post_command(e,"command/set_scheduled_departure",null,o,t)},exports.setScheduledDepartureAsync=Promise.denodeify(exports.setScheduledDeparture),exports.doorLock=function(e,o,t){post_command(e,"command/door_lock",null,null,t)},exports.doorLockAsync=Promise.denodeify(exports.doorLock),exports.doorUnlock=function(e,o,t){post_command(e,"command/door_unlock",null,null,t)},exports.doorUnlockAsync=Promise.denodeify(exports.doorUnlock),exports.climateStart=function(e,o,t){post_command(e,"command/auto_conditioning_start",null,null,t)},exports.climateStartAsync=Promise.denodeify(exports.climateStart),exports.climateStop=function(e,o,t){post_command(e,"command/auto_conditioning_stop",null,null,t)},exports.climateStopAsync=Promise.denodeify(exports.climateStop),exports.SUNROOF_VENT="vent",exports.SUNROOF_CLOSED="close",exports.sunRoofControl=function(e,o,t){post_command(e,"command/sun_roof_control",null,o,t)},exports.sunRoofControlAsync=Promise.denodeify(exports.sunRoofControl),exports.sunRoofMove=function(e,o,t){post_command(e,"command/sun_roof_control",null,{state:"move",percent:o?.percent},t)},exports.sunRoofMoveAsync=Promise.denodeify(exports.sunRoofMove),exports.MIN_TEMP=15,exports.MAX_TEMP=28,exports.setTemps=function(e,o,t){null==(o=o??{}).pass&&(o.pass=o.driver),o.driver=clamp(o.driver,exports.MIN_TEMP,exports.MAX_TEMP),o.pass=clamp(o.pass,exports.MIN_TEMP,exports.MAX_TEMP),post_command(e,"command/set_temps",null,{driver_temp:o.driver,passenger_temp:o.pass},t)},exports.setTempsAsync=Promise.denodeify(exports.setTemps),exports.remoteStart=function(e,o,t){post_command(e,"command/remote_start_drive",null,null,t)},exports.remoteStartAsync=Promise.denodeify(exports.remoteStart),exports.FRUNK="front",exports.TRUNK="rear",exports.openTrunk=function(e,o,t){post_command(e,"command/actuate_trunk",null,{which_trunk:o?.which},t)},exports.openTrunkAsync=Promise.denodeify(exports.openTrunk),exports.wakeUp=function(e,o,t){post_command(e,"wake_up",null,null,t)},exports.wakeUpAsync=Promise.denodeify(exports.wakeUp),exports.setValetMode=function(e,o,t){post_command(e,"command/set_valet_mode",null,{on:o?.onoff,password:o?.pin},t)},exports.setValetModeAsync=Promise.denodeify(exports.setValetMode),exports.resetValetPin=function(e,o,t){post_command(e,"command/reset_valet_pin",null,null,t)},exports.resetValetPinAsync=Promise.denodeify(exports.resetValetPin),exports.calendar=function(e,o,t){post_command(e,"command/upcoming_calendar_entries",null,o?.entry,t)},exports.calendarAsync=Promise.denodeify(exports.calendar),exports.makeCalendarEntry=function(e,o,t,n,s,r){return{calendar_data:{access_disabled:!1,calendars:[{color:"ff9a9cff",events:[{allday:!1,color:"ff9a9cff",end:n??Date.now(),start:t??Date.now(),cancelled:!1,tentative:!1,location:o??"",name:e??"Event name",organizer:""}],name:s??""}],phone_name:r,uuid:"333239059961778"}}},exports.homelink=function(e,o,t){post_command(e,"command/trigger_homelink",null,{lat:o?.lat,lon:o?.long},t)},exports.homelinkAsync=Promise.denodeify(exports.homelink),exports.products=function(e,o){exports.get("/api/1/products",null,o)},exports.productsAsync=Promise.denodeify(exports.products),exports.solarStatus=function(e,o){exports.get(`/api/1/energy_sites/${e.siteId}/live_status`,null,o)},exports.solarStatusAsync=Promise.denodeify(exports.solarStatus),exports.streamingColumns=["elevation","est_heading","est_lat","est_lng","est_range","heading","odometer","power","range","shift_state","speed","soc"],exports.startStreaming=function(o,t,e){log(API_CALL_LEVEL,"TeslaJS.startStreaming()"),t=t??function(e,o,t){},o.values=o.values??exports.streamingColumns;var n=new websocket(streamingBaseURI,{perMessageDeflate:!1});n.on("message",function(e){e=JSON.parse(e);"control:hello"==e.msg_type?n.send(JSON.stringify({msg_type:"data:subscribe_oauth",token:o.authToken,value:o.values.join(","),tag:o.vehicle_id.toString()})):"data:error"==e.msg_type?t("Error: "+e.value):t(null,null,e)}),n.on("close",function(){t("Websocket disconnected")}),n.on("error",function(){t("Websocket error")})};var name,nameAsync,promises={};for(name in exports)name.endsWith("Async")||((nameAsync=name+"Async")in exports?promises[name]=exports[nameAsync]:promises[name]=exports[name]);exports.promises=promises;