timdorr / tesla-api

🚘 A Ruby gem and unofficial documentation of Tesla's JSON API for the Model S, 3, X, and Y.
https://tesla-api.timdorr.com/
MIT License
2k stars 534 forks source link

Android Programming Problem using API #47

Closed dburk1013 closed 7 years ago

dburk1013 commented 7 years ago

Thanks to a number of contributors who are much wiser than I, I've got a plain vanilla version of what I'm trying to do in Java working in EclipseJavaNeon. But ultimately, I'm trying to get this into an Android app. The goal is ultimately to close an open (or vented) sunroof. There is something about how I'm using the API that's just not right (or I'm just too uneducated to be programming this stuff). There are two parts to my problem right now and a kind of third problem listed way below.


1) On the effort to get the access token, I can get the token but only if all the parameters are in the URL itself with https://private-anon-3f2af7cab3-timdorr.apiary-proxy.com/oauth/token?client_id=e4a9949fcfa04068f59abb5a658f2bac0a3428e4652315490b659d5ab3f35a9e&client_secret=c75f14bbadc8bee3a7594412c31416f8300256d7668ea7e6e7f06727bfb9d220&email=myemail@hotmail.com&password=[my password]&grant_type=password

This works but it seems as if I should be able to pass the parts either as JSON or the equivalent of headers so that it's not passed in plain text with the password. Here's the code that I'm using. This is in a separate thread as required by Android and I THINK I'm managing the Async stuff correctly. So the following works but I'd like to get the parameters out of the URL if there's a way to do it:

String realUrl = "https://owner-api.teslamotors.com/oauth/token?grant_type=password&client_id={id token}&client_secret={client secret token}&email={myemail@mydomain.com}&password={mypassword}";
URL url = null;
try {
         url = new URL(realUrl);
} catch (MalformedURLException e) {
         e.printStackTrace();
}
HttpsURLConnection myURLConnection = null;
try {
         myURLConnection = (HttpsURLConnection) url.openConnection();
} catch (IOException e) {
  e.printStackTrace();
}
try {
         myURLConnection.setRequestMethod("POST");
} catch (ProtocolException e) {
         e.printStackTrace();
}
myURLConnection.setConnectTimeout(3000);  **//THIS LINE DOESN’T SEEM TO MAKE ANY DIFFERENCE WHEN I LOOK AT DEBUG**
myURLConnection.setReadTimeout(3000);      **//DITTO WITH THIS LINE**
myURLConnection.setRequestProperty("User-Agent", "Mozilla/5.0");
myURLConnection.setRequestProperty("Content-Type", "application/json");
myURLConnection.setDoOutput(true);
myURLConnection.setDoInput(true);

_/*Tried to put all of the parameters into JSON and write it here, but this didn’t work
String json = "{\"grant_type\":"\password,client_id\":\"[id token]\","\client_secret\":"\[client secret token]\",\"email\":\"myemail@mydomain.com\",\"password\":\"mypassword\"}";
DataOutputStream dStream = null;
try {
         dStream = new DataOutputStream(myURLConnection.getOutputStream());
         dStream.writeBytes(json);
         dStream.flush();
         dStream.close();
} catch (IOException e) {
         e.printStackTrace();
} */_

int response = 0;
try {
         response = myURLConnection.getResponseCode();
} catch (IOException e) {
         e.printStackTrace();
}
StringBuffer result = new StringBuffer();
BufferedReader rd;
try {
         rd = new BufferedReader(new InputStreamReader(myURLConnection.getInputStream()));
         String line = "";
         while ((line = rd.readLine()) != null) {
                 result.append(line);
         }
         rd.close();
} catch (IOException e) {
         e.printStackTrace();
}
myURLConnection.disconnect();
accessToken = [subroutine pulls global String accessToken from result; works];
return;

2) Once I have a good access token, I'm next trying to get the vehicleID. The following code is returning a 404 from the server. I suspect I'm missing something really easy and obvious. Any help here again would be greatly appreciated:

String realUrl = "https://owner-api.teslamotors.com/api/1/vehicles";
URL url = null;
try {
         url = new URL(realUrl);
} catch (MalformedURLException e) {
         e.printStackTrace();
}
HttpsURLConnection myURLConnection = null;
try {
         myURLConnection = (HttpsURLConnection) url.openConnection();
} catch (IOException e) {
  e.printStackTrace();
}
try {
         myURLConnection.setRequestMethod("GET");
} catch (ProtocolException e) {
         e.printStackTrace();
}
myURLConnection.setConnectTimeout(3000);  **//THIS LINE DOESN’T SEEM TO MAKE ANY DIFFERENCE WHEN I LOOK AT DEBUG**
myURLConnection.setReadTimeout(3000);      **//DITTO WITH THIS LINE**
myURLConnection.setRequestProperty("User-Agent", "Mozilla/5.0");
myURLConnection.setDoOutput(true);
myURLConnection.setDoInput(true);
myURLConnection.setRequestProperty("Authorization", "Bearer " + accessToken); //accessToken is global variable set in getAuth()

int response = 0;
try {
         response = myURLConnection.getResponseCode();
         **//response = 404!!!!**
} catch (IOException e) {
         e.printStackTrace();
}
StringBuffer result = new StringBuffer();
BufferedReader rd;
try {
         rd = new BufferedReader(new InputStreamReader(myURLConnection.getInputStream()));
         String line = "";
         while ((line = rd.readLine()) != null) {
                 result.append(line);
         }
         rd.close();
} catch (IOException e) {
         e.printStackTrace();
}
myURLConnection.disconnect();
vehicleID = [subroutine pulls global String vehicleID from result; probably works but haven’t gotten useful result yet];
return;

3. If anyone has any thoughts about why the .setConnectTimeout and .setReadTimeout methods don't seem to be changing the values for the properties when I'm looking the debugger either for myURLConnection or for the delegate property of myURLConnection, again, I would appreciate your ideas. As a related item, I learned that the .setRequestMethod, .setDoOutput, and .setDoInput methods don't change these properties for myURLConnection but do set these properties for the delegate, but this doesn't happen for the . ...Timeout methods. Why?

THANK YOU!

dburk1013 commented 7 years ago

I found or have been helped with the answers to all 3 so this can be closed. 1) I understand that, even though getting the authorization token is in a "POST", apparently the Tesla servers are still expecting the parameters to be passed on the URL line. I wish it weren't so, but maybe there's no alternative. 2) If there is no output to go to Tesla (as there wouldn't be with a "GET"), the myURLConnection.setDoOutput(true) results in a 404 error. If you have a GET type, seems the setDoOutput(true) creates a problem. Remove the line and it works! 3) .setConnectTimeout and .setReadTimeout changes show as properties of myURLConnection.delegate.client. You have to dig deep enough to see the changes.

Thanks to everyone who had any thoughts on any of this.