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: 1764
Threads: 6
Joined: Jul 2015
Reputation:
117
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: 1764
Threads: 6
Joined: Jul 2015
Reputation:
117
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: 1764
Threads: 6
Joined: Jul 2015
Reputation:
117
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: 1764
Threads: 6
Joined: Jul 2015
Reputation:
117
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: 449
Threads: 94
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: 449
Threads: 94
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: 7769
Threads: 42
Joined: Jun 2015
Reputation:
447
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: 7769
Threads: 42
Joined: Jun 2015
Reputation:
447
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: 7769
Threads: 42
Joined: Jun 2015
Reputation:
447
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!!!
|