Hi, I finally got these working by following the different advices in this thread and some googling. I especially wanted to control the rate of charge and charging limit. After some fiddling, I found out that these needs the arguments in the body.
Code:
-- Load modules
encdec = require('encdec')
http = require('socket.http')
mime = require('mime')
ltn12 = require('ltn12')
json = require('json')
https = require('ssl.https')
-- set credentials
username = 'some@email.com'
password = 'somepwd'
client_id = "replace" -- default, do not change unless Tesla makes changes
client_secret = "replace" -- default, do not change unless Tesla makes changes
-- all Tesla devices
tesla = {} -- car, vehicle_id
tesla[1] = {'myCar1', 'id_s'}
CarID = tesla[1][2] -- 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!
--Update using the Auth for Tesla app:
RefreshToken_App= "ey...XYZ"
AccessToken_App = "ey...123"
function GetToken()
-- 1. get current refresh_token from storage (you will have to store it manually once)
RefreshToken = storage.get('TeslaRefresh')
-- 2. request new access_token and refresh_token using current refresh_token
body = json.encode({
grant_type = 'refresh_token',
client_id = 'ownerapi',
refresh_token = RefreshToken,
scope = 'openid email offline_access'
})
resp = {}
res, code, headers = http.request({
url = 'https://auth.tesla.com/oauth2/v3/token',
method = 'POST',
source = ltn12.source.string(body),
sink = ltn12.sink.table(resp),
headers = {
['Content-Type'] = 'application/json',
['Accept'] = 'application/json',
['Content-Length'] = #body,
['User-Agent'] = 'Mozilla/5.0 (Linux; Android 9.0.0; VS985 4G Build/LRX21Y; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/58.0.3029.83 Mobile Safari/537.36',
['X-Tesla-User-Agent'] = 'TeslaApp/3.4.4-350/fad4a582e/android/9.0.0'
}
})
if not res or code ~= 200 then
log('Failed to Tesla API tokens', resp, res, code)
return
end
resp = table.concat(resp)
resp = json.pdecode(resp)
-- 3. save new access_token and new refresh_token to storage
storage.set('TeslaAccess', resp.access_token)
storage.set('TeslaRefresh', resp.refresh_token)
log('Tesla tokens successfully updated')
log('New access token: ' .. resp.access_token)
log('New refresh token: ' .. resp.refresh_token)
end
function RequestFromTesla(request)
API_Token = storage.get('TeslaAccess')
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
GetToken() -- request a new token
log('Request from Tesla API failed ', code, ret)
end
end
function WriteToTesla(request, request_body)
API_Token = storage.get('TeslaAccess')
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
log('Write to Tesla API failed ', code, ret)
GetToken() -- request a new token
end
end
---------------------------------------------------------------------------------------
-- Get products
function get_products()
products = RequestFromTesla('products')
return(products) -- Check here your product ID
end
-- Get vehicles
function get_vehicles()
vehicles = RequestFromTesla('vehicles')
return(vehicles) -- Check here your Vehicles
end
-- Get onboarding data
function get_onboarding_data()
onboarding_data = RequestFromTesla('users/onboarding_data')
return(onboarding_data)
end
-- Get vehicle data
function get_vehicle_data()
vehicle_data = RequestFromTesla('vehicles/' .. CarID .. '/vehicle_data')
return(vehicle_data)
end
-- Get vehicle charge state
function get_charge_state()
charge_state = RequestFromTesla('vehicles/' .. CarID .. '/data_request/charge_state')
return(charge_state)
end
-- Get vehicle state
function get_vehicle_state()
vehicle_state = RequestFromTesla('vehicles/' .. CarID .. '/data_request/vehicle_state')
return(vehicle_state)
end
-- Get drive state
function get_drive_state()
drive_state = RequestFromTesla('vehicles/' .. CarID .. '/data_request/drive_state')
return(drive_state)
end
-- Wake up car
function wake_up()
result = WriteToTesla('vehicles/' .. CarID .. '/wake_up')
debugLog(result)
end
-- Unlock car
function door_unlock()
result = WriteToTesla('vehicles/' .. CarID .. '/command/door_unlock')
return(result)
end
-- Lock car
function door_lock()
result = WriteToTesla('vehicles/' .. CarID .. '/command/door_lock')
return(result)
end
-- Honk horn
function honk_horn()
result = WriteToTesla('vehicles/' .. CarID .. '/command/honk_horn')
return(result)
end
-- Flash lights
function flash_lights()
result = WriteToTesla('vehicles/' .. CarID .. '/command/flash_lights')
return(result)
end
-- Autocondition start
function auto_conditioning_start()
result = WriteToTesla('vehicles/' .. CarID .. '/command/auto_conditioning_start')
return(result)
end
-- Autocondition stop
function auto_conditioning_stop()
result = WriteToTesla('vehicles/' .. CarID .. '/command/auto_conditioning_stop')
return(result)
end
-- Set temperature
function set_temps(iDriverTemp,iPassengerTemp)
result = WriteToTesla('vehicles/' .. CarID .. '/command/set_temps?driver_temp='..iDriverTemp..'&passenger_temp='..iPassengerTemp)
return(result)
end
-- Charge port door open
function charge_port_door_open()
result = WriteToTesla('vehicles/' .. CarID .. '/command/charge_port_door_open')
return(result)
end
-- Set charging current: PS needs argument in body
function set_charging_current(iChargingAmps)
result = WriteToTesla('vehicles/' .. CarID .. '/command/set_charging_amps', '{"charging_amps":"'..iChargingAmps..'"}')
return(result)
end
-- Set charging limit:
function set_charge_limit(iChargingLimit)
result = WriteToTesla('vehicles/' .. CarID .. '/command/set_charge_limit', '{"percent":"'..iChargingLimit..'"}')
return(result)
end
-- Start charging
function charge_start()
result = WriteToTesla('vehicles/' .. CarID .. '/command/charge_start')
return(result)
end
-- Stop charging
function charge_stop()
result = WriteToTesla('vehicles/' .. CarID .. '/command/charge_stop')
return(result)
end
-- Charge to standard limit (90%)
function charge_standard()
result = WriteToTesla('vehicles/' .. CarID .. '/command/charge_standard')
return(result)
end
-- Charge to max range (100%)
function charge_standard()
result = WriteToTesla('vehicles/' .. CarID .. '/command/charge_max_range')
return(result)
end
-- Open trunk rear
function actuate_trunk()
result = WriteToTesla('vehicles/' .. CarID .. '/command/actuate_trunk', '{"which_trunk":"rear"}')
return(result)
end
-- Open trunk front
function actuate_frunk()
result = WriteToTesla('vehicles/' .. CarID .. '/command/actuate_trunk', '{"which_trunk":"front"}')
return(result)
end