This forum uses cookies
This forum makes use of cookies to store your login information if you are registered, and your last visit if you are not. Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. Cookies on this forum also track the specific topics you have read and when you last read them. Please confirm that you accept these cookies being set.

Help with Tesla Powerwall API V3
#9
This is due to outdated libraries in your firmware. Unfortunately it's not possible to update these libraries separately.
See if this works for you:
Code:
username = 'user@domain.com'
password = 'password'
client_id = 'ID'
client_secret = 'SECRET'

encdec = require('encdec')
http = require('socket.http')
mime = require('mime')
ltn12 = require('ltn12')
json = require('json')

function mt()
  local ts, tu = os.microtime()
  return ts .. '.' .. tu
end

function b64url(str)
  return mime.b64(str):gsub('.', {
    ['+'] = '-',
    ['/'] = '_',
    ['='] = '',
  })
end

function encodeargs(t)
  local res = {}
  local esc = require('socket.url').escape

  for k, v in pairs(t) do
    res[ #res + 1 ] = esc(k) .. '=' .. esc(v)
  end

  return table.concat(res, '&')
end

rnd = encdec.sha256(mt())
code_verifier = (rnd .. rnd):sub(1, 86)
state = b64url(rnd:sub(1, 12))
code_challenge = b64url(code_verifier)

args = encodeargs({
  client_id = 'ownerapi',
  code_challenge = code_challenge,
  code_challenge_method = 'S256',
  redirect_uri = 'https://auth.tesla.com/void/callback',
  response_type = 'code',
  scope = 'openid email offline_access',
  state = state,
})

resp = {}

url = 'https://auth.tesla.com/oauth2/v3/authorize?' .. args
res, code, headers = http.request({
  url = url,
  sink = ltn12.sink.table(resp),
  protocol = 'tlsv12',
})

if not res or code ~= 200 then
  log('request 1 failed', res, code)
  return
end

postdata = {}
regexp = '<input type="hidden" name="([^"]+)" value="([^"]*)"'

resp = table.concat(resp)
for name, value in resp:gmatch(regexp) do
  postdata[ name ] = value
end

postdata.identity = username
postdata.credential = password

cookie = headers['Set-Cookie'] or headers['set-cookie'] or ''
body = encodeargs(postdata)

res, code, headers = http.request({
  url = url,
  method = 'POST',
  source = ltn12.source.string(body),
  protocol = 'tlsv12',
  headers = {
    ['Content-Type'] = 'application/x-www-form-urlencoded',
    ['Content-Length'] = #body,
    ['Cookie'] = cookie,
  }
})

if not res or code ~= 302 then
  log('request 2 failed', res, code)
  return
end

hdr = headers.Location or headers.location
resp_code = hdr:match('code=([^&]+)')

body = json.encode({
  grant_type = 'authorization_code',
  client_id = 'ownerapi',
  code = resp_code,
  code_verifier = code_verifier,
  redirect_uri = 'https://auth.tesla.com/void/callback',
})

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),
  protocol = 'tlsv12',
  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('request 3 failed', res, code)
  return
end

resp = table.concat(resp)
resp = json.pdecode(resp)

bearer_token = resp.access_token
refresh_token = resp.refresh_token

body = json.encode({
  grant_type = 'urn:ietf:params:oauth:grant-type:jwt-bearer',
  client_id = client_id,
  client_secret = client_secret,
})

resp = {}

res, code, headers = http.request({
  url = 'https://owner-api.teslamotors.com/oauth/token',
  method = 'POST',
  source = ltn12.source.string(body),
  sink = ltn12.sink.table(resp),
  protocol = 'tlsv12',
  headers = {
    ['Content-Type'] = 'application/json',
    ['Authorization'] = 'Bearer ' .. bearer_token,
    ['Content-Length'] = #body,
  }
})

print(res, code)
if not res or code ~= 200 then
  log('request 4 failed', res, code)
  return
end

resp = table.concat(resp)
resp = json.pdecode(resp)

access_token = resp.access_token
log(access_token)
Reply


Messages In This Thread
Help with Tesla Powerwall API V3 - by jamesng - 21.04.2021, 14:18
RE: Help with Tesla Powerwall API V3 - by admin - 26.04.2021, 07:02

Forum Jump: