Posts: 136 
	Threads: 18 
	Joined: Apr 2017
	
 Reputation: 
 1
	 
 
	
	
		Hi, 
I have Tesla and recently discovered the possibility to use HTTP to send commands and receive status from the car. 
Unfortunately I am not so good with scripts/coding.
 
Hopefully someone here can give me a helping hand.
 
I wold like to have the spacelynk to send a post the following HTTP url, with this header...
 https://owner-api.teslamotors.com/api/1/...ning_start
Header: bearer (string) 987654321
 
This I would like to incorporate in an event script.
 
if value == true then 
post HTTP 
end
 
Anyone?
	  
	
	
BR, 
Mr.D
 
	
		
	 
 
 
	
	
	
		
	Posts: 1807 
	Threads: 7 
	Joined: Jul 2015
	
 Reputation: 
 121
	 
 
	
		
		
		13.12.2018, 19:54 
(This post was last modified: 13.12.2018, 19:55 by Erwin van der Zwart.)
		
	 
	
		Hi, 
 
When i have the API documentation i will probably need few minutes to create it.  
 
I just created a script for our Ecostruxure Building Operations SmartConnector and this also uses a bearer token that you need to request first before you can use the API and that took me 25 minutes. 
 
The link you sended is not working.. 
 
Please send the API document and i see what i can do, holidays are comming (: 
 
BR, 
 
Erwin
	 
	
	
	
		
	 
 
 
	
	
	
		
	Posts: 136 
	Threads: 18 
	Joined: Apr 2017
	
 Reputation: 
 1
	 
 
	
		
		
		13.12.2018, 19:59 
(This post was last modified: 13.12.2018, 20:05 by Mr.D.)
		
	 
	
		Hi Erwin, 
I already have the bearer token so basically all I have to do is POST this HTTP command: 
"https://owner-api.teslamotors.com/api/1/vehicles/123/command/auto_conditioning_start" 
 but I need to include the bearer token in the header... 
 
something like this????
 
curl --request POST \ 
  --url "https://owner-api.teslamotors.com/api/1/vehicles/123/command/auto_conditioning_start \" 
  --header 'Authorization: Bearer 123
 
Here is the link to the API
 https://www.teslaapi.io/vehicles/commands
	 
	
	
BR, 
Mr.D
 
	
		
	 
 
 
	
	
	
		
	Posts: 1807 
	Threads: 7 
	Joined: Jul 2015
	
 Reputation: 
 121
	 
 
	
		
		
		13.12.2018, 22:50 
(This post was last modified: 13.12.2018, 23:11 by Erwin van der Zwart.)
		
	 
	
		Hi, 
Usually the bearer token is a response on the token request and is valid for x minutes (mostly 60 minutes), so i doubt that 123 is the bearer code (: 
 
Can you try this?
 Code: -- Load modules 
require('json') 
require('ssl.https') 
require('ltn12') 
 
-- Set credentials for Tesla API 
username = "admin" 
password = "admin" 
 
function GetToken() 
  request_token_url = 'https://owner-api.teslamotors.com/oauth/token' 
  local response_body = {} 
  local request_body = "grant_type=password&username=" .. username .. "&password=" .. password 
  local body, code, hdrs, stat = ssl.https.request{ 
    url = request_token_url; 
    method = "POST"; 
    headers = 
    { 
      ["Content-Type"] = "application/x-www-form-urlencoded"; 
      ["Content-Length"] = #request_body; 
    }; 
    source = ltn12.source.string(request_body); 
    sink = ltn12.sink.table(response_body); 
  } 
  if code == 200 then 
    ret = table.concat(response_body) 
    ret = json.pdecode(ret) 
    return ret.access_token -- could be some other field, try to log ret to be sure 
  end 
end 
 
-- Request token 
if not API_Token then 
    API_Token = GetToken() 
end 
 
function RequestFromTesla(request) 
  request_url = 'https://owner-api.teslamotors.com/api/1/' .. request 
  local response_body = {} 
  local request_body = "" 
  local body, code, hdrs, stat = ssl.https.request{ 
    url = request_url; 
    method = "GET"; 
    headers = 
    { 
      ["Content-Type"] = "application/json"; 
      ["Authorization"] = "Bearer " .. API_Token; 
    }; 
    source = ltn12.source.string(request_body); 
    sink = ltn12.sink.table(response_body); 
  } 
  if code == 200 then 
    ret = table.concat(response_body) 
    ret = json.pdecode(ret) 
    return ret 
  else  
    API_Token = GetToken() -- request a new token 
  end 
end 
 
function WriteToTesla(request) 
  request_url = 'https://owner-api.teslamotors.com/api/1/' .. request 
  local response_body = {} 
  local request_body = "" 
  local body, code, hdrs, stat = ssl.https.request{ 
    url = request_url; 
    method = "POST"; 
    headers = 
    { 
      ["Content-Type"] = "application/json"; 
      ["Authorization"] = "Bearer " .. API_Token; 
    }; 
    source = ltn12.source.string(request_body); 
    sink = ltn12.sink.table(response_body); 
  } 
  if code == 200 then 
    ret = table.concat(response_body) 
    ret = json.pdecode(ret) 
    return ret 
  else  
    API_Token = GetToken() -- request a new token 
  end 
end 
 
-- Get products 
products = RequestFromTesla('products') 
log(products) -- Check here your Car ID 
 
CarID = 1 -- products[1].id? 
 
-- Get onboarding data 
onboarding_data = RequestFromTesla('users/onboarding_data') 
log(onboarding_data) 
 
-- Wake up car 
result = WriteToTesla('vehicles/' .. CarID .. '/wake_up') 
log(result)
 BR,
 
Erwin
	  
	
	
	
		
	 
 
 
	
	
	
		
	Posts: 136 
	Threads: 18 
	Joined: Apr 2017
	
 Reputation: 
 1
	 
 
	
	
		 (13.12.2018, 22:50)Erwin van der Zwart Wrote:  Hi, 
 
Usually the bearer token is a response on the token request and is valid for x minutes (mostly 60 minutes), so i doubt that 123 is the bearer code (:  
 
Can you try this? 
Code: -- Load modules 
require('json') 
require('ssl.https') 
require('ltn12') 
 
-- Set credentials for Tesla API 
username = "admin" 
password = "admin" 
 
function GetToken() 
  request_token_url = 'https://owner-api.teslamotors.com/oauth/token' 
  local response_body = {} 
  local request_body = "grant_type=password&username=" .. username .. "&password=" .. password 
  local body, code, hdrs, stat = ssl.https.request{ 
    url = request_token_url; 
    method = "POST"; 
    headers = 
    { 
      ["Content-Type"] = "application/x-www-form-urlencoded"; 
      ["Content-Length"] = #request_body; 
    }; 
    source = ltn12.source.string(request_body); 
    sink = ltn12.sink.table(response_body); 
  } 
  if code == 200 then 
    ret = table.concat(response_body) 
    ret = json.pdecode(ret) 
    return ret.access_token -- could be some other field, try to log ret to be sure 
  end 
end 
 
-- Request token 
if not API_Token then 
    API_Token = GetToken() 
end 
 
function RequestFromTesla(request) 
  request_url = 'https://owner-api.teslamotors.com/api/1/' .. request 
  local response_body = {} 
  local request_body = "" 
  local body, code, hdrs, stat = ssl.https.request{ 
    url = request_url; 
    method = "GET"; 
    headers = 
    { 
      ["Content-Type"] = "application/json"; 
      ["Authorization"] = "Bearer " .. API_Token; 
    }; 
    source = ltn12.source.string(request_body); 
    sink = ltn12.sink.table(response_body); 
  } 
  if code == 200 then 
    ret = table.concat(response_body) 
    ret = json.pdecode(ret) 
    return ret 
  else  
    API_Token = GetToken() -- request a new token 
  end 
end 
 
function WriteToTesla(request) 
  request_url = 'https://owner-api.teslamotors.com/api/1/' .. request 
  local response_body = {} 
  local request_body = "" 
  local body, code, hdrs, stat = ssl.https.request{ 
    url = request_url; 
    method = "POST"; 
    headers = 
    { 
      ["Content-Type"] = "application/json"; 
      ["Authorization"] = "Bearer " .. API_Token; 
    }; 
    source = ltn12.source.string(request_body); 
    sink = ltn12.sink.table(response_body); 
  } 
  if code == 200 then 
    ret = table.concat(response_body) 
    ret = json.pdecode(ret) 
    return ret 
  else  
    API_Token = GetToken() -- request a new token 
  end 
end 
 
-- Get products 
products = RequestFromTesla('products') 
log(products) -- Check here your Car ID 
 
CarID = 1 -- products[1].id? 
 
-- Get onboarding data 
onboarding_data = RequestFromTesla('users/onboarding_data') 
log(onboarding_data) 
 
-- Wake up car 
result = WriteToTesla('vehicles/' .. CarID .. '/wake_up') 
log(result)
  BR, 
 
Erwin 
Hi,
 
If I understand your script correctly this will get me the bearer token? and then some? 
I already have the token, and you are correct, it is not 123. I just wrote that because I did not want to expose the token. Doing so, the token together with the Vehicle ID/Car ID I would give everyone access to my car   
In terms of how long the token last, a Tesla token lasts for 30 days before it needs to be refreshed.
 
I already have the Vehicle ID, which is part of the URL. 
What I need is to understand how I send a POST request that includes the URL but also the bearer token... I do not know how to add the bearer token as part of my URL request...
 
But I see your script is way more advanced, in fear of asking too much could you explain what your script does? in terms of the different functions? I see that storing and using the response from the car adds some further potentials in terms of adding "features" to my smarthouse/tesla   
	 
	
	
BR, 
Mr.D
 
	
		
	 
 
 
	
	
	
		
	Posts: 1807 
	Threads: 7 
	Joined: Jul 2015
	
 Reputation: 
 121
	 
 
	
		
		
		14.12.2018, 20:04 
(This post was last modified: 14.12.2018, 20:12 by Erwin van der Zwart.)
		
	 
	
		Hi, 
The function GetToken() does a request to the API with your credentials and returns the Bearer Token so you don't have to look it up all the time. Its returned in the table 'ret' inside de function, i think the field is access_token but you need to check that by adding log(ret) in the function to see what fields are returned. the variable API_Token should be automatically filled with a valid token and will be used in the further API requests. (is already include in the other functions as Authorization header so you dont need to change anything)
 
The function RequestFromTesla(request) should be used for all GET requests and the static part of the URL is already included to the function so you only have to pass the latest part of the URL as request variable so RequestFromTesla("products") will actually request the URL  https://owner-api.teslamotors.com/api/1/products and returns the response as a table where all your Tesla product should be listed. I think the ID is also a field in this returned table that you could use in next requests as variable as 'product.id'
 
The function WriteToTesla(request) should be used for all POST commands and here is also the static part of the URL already included to the function, here you also only need to pass the latest part of the URL as request variable and returns the response as table (probably returns 'success' or something)
 
So with these 3 functions you should be able to request the token, request data and write data from/to the vehicle.
 
Basically you only need to set your username & passwords and use the 2 functions RequestFromTesla(request) + WriteToTesla(request) to exchange data with your car. 
 
Succes!
 
BR,
 
Erwin
	  
	
	
	
		
	 
 
 
	
	
	
		
	Posts: 136 
	Threads: 18 
	Joined: Apr 2017
	
 Reputation: 
 1
	 
 
	
		
		
		27.01.2019, 12:04 
(This post was last modified: 27.01.2019, 16:12 by Mr.D.)
		
	 
	
		Hi, 
In terms of the Token... this only last for 45 days. The script you made, will this ask for a new token every time it is run?
 
For some commands they require and extra "field/input"... 
Like the Start Drive Command, this one requires a password as well
 https://www.teslaapi.io/vehicles/commands
How do I incorporate this into the script?
 
I also made som changes to the script, for anyone that plans to do this, I can confirm this works: 
PS: you must run the script once, so you can get your vehicle ID. Look in the logs and replace the 123 for CarID
 Code: -- Load modules 
require('json') 
require('ssl.https') 
require('ltn12') 
 
-- Set credentials for Tesla API 
username = "abc" -- your email for tesla account 
password = "123" -- your password for tesla account 
password1 = "password" -- default do not change 
client_id = "81527cff06843c8634fdc09e8ac0abefb46ac849f38fe1e431c2ef2106796384" -- default, do not change unless Tesla makes changes 
client_secret = "c7257eb71a564034f9419ee651c7d0e5f7aa6bfbd18bafb5c5c033b093bb2fa3" -- default, do not change unless Tesla makes changes 
 
function GetToken() 
  request_token_url = 'https://owner-api.teslamotors.com/oauth/token' 
  local response_body = {} 
  local request_body = "grant_type=" .. password1 .. "&client_id=" .. client_id .. "&client_secret=" .. client_secret .. "&email=" .. username .. "&password=" .. password 
  local body, code, hdrs, stat = ssl.https.request{ 
    url = request_token_url; 
    method = "POST"; 
    headers = 
    { 
      ["Content-Type"] = "application/x-www-form-urlencoded"; 
      ["Content-Length"] = #request_body; 
    }; 
    source = ltn12.source.string(request_body); 
    sink = ltn12.sink.table(response_body); 
  } 
  if code == 200 then 
    ret = table.concat(response_body) 
    ret = json.pdecode(ret) 
    return ret.access_token 
  end 
end 
 
-- Request token 
if not API_Token then 
    API_Token = GetToken() 
end 
 
function RequestFromTesla(request) 
  request_url = 'https://owner-api.teslamotors.com/api/1/' .. request 
  local response_body = {} 
  local request_body = "" 
  local body, code, hdrs, stat = ssl.https.request{ 
    url = request_url; 
    method = "GET"; 
    headers = 
    { 
      ["Content-Type"] = "application/json"; 
      ["Authorization"] = "Bearer " .. API_Token; 
    }; 
    source = ltn12.source.string(request_body); 
    sink = ltn12.sink.table(response_body); 
  } 
  if code == 200 then 
    ret = table.concat(response_body) 
    ret = json.pdecode(ret) 
    return ret 
  else  
    API_Token = GetToken() -- request a new token 
  end 
end 
 
function WriteToTesla(request) 
  request_url = 'https://owner-api.teslamotors.com/api/1/' .. request 
  local response_body = {} 
  local request_body = "" 
  local body, code, hdrs, stat = ssl.https.request{ 
    url = request_url; 
    method = "POST"; 
    headers = 
    { 
      ["Content-Type"] = "application/json"; 
      ["Authorization"] = "Bearer " .. API_Token; 
    }; 
    source = ltn12.source.string(request_body); 
    sink = ltn12.sink.table(response_body); 
  } 
  if code == 200 then 
    ret = table.concat(response_body) 
    ret = json.pdecode(ret) 
    return ret 
  else  
    API_Token = GetToken() -- request a new token 
  end 
end 
 
-- Get products 
products = RequestFromTesla('products') 
log(products) -- Check here your Car ID 
 
CarID = 123 -- run the script once, and look in the logs you will find a string called id_s this number is your vehicle ID, this should be replaced with the 123 in this field, remember to add "", then run script again, and you will get it to work! 
 
-- Get onboarding data 
onboarding_data = RequestFromTesla('users/onboarding_data') 
log(onboarding_data) 
 
-- unlock car 
result = WriteToTesla('vehicles/' .. CarID .. '/command/door_unlock') 
log(result)
  
	 
	
	
BR, 
Mr.D
 
	
		
	 
 
 
	
	
	
		
	Posts: 1807 
	Threads: 7 
	Joined: Jul 2015
	
 Reputation: 
 121
	 
 
	
	
		Hi, 
 
If you use this script as event based it will request the token every run, if you use it as resident then the token is reqeusted once and when the connection is responding with a error code (other code then 200) then the token is requested again and the script will use this new token until the next error code (other code then 200). 
 
BR, 
 
Erwin
	 
	
	
	
		
	 
 
 
	
	
	
		
	Posts: 477 
	Threads: 100 
	Joined: Jun 2015
	
 Reputation: 
 6
	 
 
	
		
		
		09.01.2020, 13:30 
(This post was last modified: 09.01.2020, 14:04 by gjniewenhuijse.)
		
	 
	
		Anyone got this working? I try to connect to my Tesla but when i execute a RequestFromTesla call it returns always nil. 
 
Before it logs my carid and filled it in the script. 
 
Onboard date returns: 
* table: 
 [response] 
  * table: 
   [entry_point_text] 
    * string: Video Guides 
   [display_page_on_startup] 
    * userdata: NULL 
   [show_in_menu] 
    * bool: false 
   [show_on_login] 
    * bool: false 
   [show_postdelivery_on_startup] 
    * bool: false 
  
solved: CarId between ""
	
	
	
	
		
	 
 
 
	
	
	
		
	Posts: 477 
	Threads: 100 
	Joined: Jun 2015
	
 Reputation: 
 6
	 
 
	
		
		
		10.01.2020, 08:14 
(This post was last modified: 10.01.2020, 08:18 by gjniewenhuijse.)
		
	 
	
		And how to open de trunk or frunc? 
You need to specify which trunc but the following code doesn't work:
 result = WriteToTesla('vehicles/' .. CarID .. '/command/actuate_trunk?which_trunk=rear')
I read something to specify this in the body, like: {"which_trunk":"rear"} 
But how to do this?
 
See:  https://tesla-api.timdorr.com/vehicle/commands/trunk
	 
	
	
	
		
	 
 
 
	
	
	
		
	Posts: 8423 
	Threads: 45 
	Joined: Jun 2015
	
 Reputation: 
 481
	 
 
	
	
		Try this: 
Code: function WriteToTesla(request, request_body) 
  request_url = 'https://owner-api.teslamotors.com/api/1/' .. request 
  local response_body = {} 
  local content_length 
 
  if type(request_body) == "string" then 
    content_length = #request_body 
  else 
    request_body = "" 
  end 
 
  local body, code, hdrs, stat = ssl.https.request{ 
    url = request_url; 
    method = "POST"; 
    headers = 
    { 
      ["Content-Type"] = "application/json"; 
      ["Authorization"] = "Bearer " .. API_Token; 
      ["Content-Length"] = content_length; 
    }; 
    source = ltn12.source.string(request_body); 
    sink = ltn12.sink.table(response_body); 
  } 
  if code == 200 then 
    ret = table.concat(response_body) 
    ret = json.pdecode(ret) 
    return ret 
  else  
    API_Token = GetToken() -- request a new token 
  end 
end 
 
result = WriteToTesla('vehicles/' .. CarID .. '/command/actuate_trunk', '{"which_trunk":"rear"}')
  
	 
	
	
	
		
	 
 
 
	
	
	
		
	Posts: 38 
	Threads: 7 
	Joined: Feb 2020
	
 Reputation: 
 0
	 
 
	
	
		Dear friends, 
Please help to create a https.request  
How should I build a request_body with next parameters:
 
Requests are sent to the following endpoint: POST  https://api.windy.com/api/point-forecast/v2 with the following body: 
{ 
    "lat": 49.809, 
    "lon": 16.787, 
    "model": "gfs", 
    "parameters": ["wind", "dewpoint", "rh", "pressure"], 
    "levels": ["surface", "800h", "300h"], 
    "key": "abcd123" 
}
 
Thank you!!
	  
	
	
	
		
	 
 
 
	
	
	
		
	Posts: 8423 
	Threads: 45 
	Joined: Jun 2015
	
 Reputation: 
 481
	 
 
	
	
		Use this: 
Code: https = require('ssl.https') 
 
url = 'https://api.windy.com/api/point-forecast/v2' 
body = [[{ 
"lat": 49.809, 
"lon": 16.787, 
"model": "gfs", 
"parameters": ["wind", "dewpoint", "rh", "pressure"], 
"levels": ["surface", "800h", "300h"], 
"key": "abcd123" 
}]] 
 
resp = {} 
 
res, code, hdrs, stat = https.request({ 
  url = url, 
  method = 'POST', 
  headers = { 
    ['Content-Type'] = 'application/json', 
    ['Content-Length'] = #body, 
  }, 
  source = ltn12.source.string(body), 
  sink = ltn12.sink.table(resp), 
}) 
 
resp = table.concat(resp) 
log(res, code, hdrs, stat, resp)
  
	 
	
	
	
		
	 
 
 
	
	
	
		
	Posts: 38 
	Threads: 7 
	Joined: Feb 2020
	
 Reputation: 
 0
	 
 
	
	
		Thank you! Tried some similar way, tried your script,  log is: 
* arg: 1 
  * nil 
* arg: 2 
  * string: error:1409442E:lib(20):func(148):reason(1070) 
* arg: 3 
  * nil 
* arg: 4 
  * nil 
* arg: 5 
  * string:
	 
	
	
	
		
	 
 
 
	
	
	
		
	Posts: 8423 
	Threads: 45 
	Joined: Jun 2015
	
 Reputation: 
 481
	 
 
	
	
		This is due to older FW that you're using. Change request parameters to this: 
Code: res, code, hdrs, stat = https.request({ 
  url = url, 
  method = 'POST', 
  protocol = 'tlsv12', 
  headers = { 
    ['Content-Type'] = 'application/json', 
    ['Content-Length'] = #body, 
  }, 
  source = ltn12.source.string(body), 
  sink = ltn12.sink.table(resp), 
})
  
	 
	
	
	
		
	 
 
 
	
	
	
		
	Posts: 38 
	Threads: 7 
	Joined: Feb 2020
	
 Reputation: 
 0
	 
 
	
	
		Thank you!!! Now it works!!!
	 
	
	
	
		
	 
 
 
	 
 |