Skip to content

Commit

Permalink
#4 tryout option2: refactor to use BLE command SDK for vehicle commands
Browse files Browse the repository at this point in the history
  • Loading branch information
erwin1 committed May 30, 2024
1 parent 152522e commit f255166
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 83 deletions.
143 changes: 61 additions & 82 deletions src/main/java/homecontrol/impl/tesla/TeslaClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import homecontrol.services.ev.EVState;
import io.vertx.core.json.JsonObject;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
Expand All @@ -12,6 +13,7 @@
import java.time.Instant;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;

public class TeslaClient {
public static final Logger LOGGER = Logger.getLogger(TeslaClient.class.getName());
Expand All @@ -21,10 +23,20 @@ public class TeslaClient {
private String refreshToken;
private String vehicle;
private String accessToken;
private String vin;
private String keyName;
private String tokenName;
private String sdkDir;
private String cacheFile;

public TeslaClient(String refreshToken, String vehicle) {
public TeslaClient(String refreshToken, String vehicle, String vin, String keyName, String tokenName, String sdkDir, String cacheFile) {
this.refreshToken = refreshToken;
this.vehicle = vehicle;
this.vin = vin;
this.keyName = keyName;
this.tokenName = tokenName;
this.sdkDir = sdkDir;
this.cacheFile = cacheFile;
}

public EVState getChargeState() throws TeslaException {
Expand Down Expand Up @@ -54,104 +66,71 @@ public EVState getChargeState() throws TeslaException {
}

public boolean openChargePortDoor() throws TeslaException {
if (accessToken == null) {
accessToken = getAccessToken(refreshToken);
}
HttpRequest request = HttpRequest.newBuilder()
.timeout(Duration.ofSeconds(10))
.uri(URI.create(BASE + "/api/1/vehicles/"+vehicle+"/command/charge_port_door_open"))
.header("Accept", "application/json")
.header("Authorization", "Bearer " + accessToken)
.POST(HttpRequest.BodyPublishers.ofString("{}"))
.build();
JsonObject responseObject = sendRequest(request);
boolean result = responseObject.getJsonObject("response").getBoolean("result");
LOGGER.log(Level.INFO, "charge poort door open. result = {0}", result);
return result;
executeCommand("charge-port-open");
return true;
}

public boolean setChargingAmps(int amps) throws TeslaException {
if (accessToken == null) {
accessToken = getAccessToken(refreshToken);
}
HttpRequest request = HttpRequest.newBuilder()
.timeout(Duration.ofSeconds(10))
.uri(URI.create(BASE + "/api/1/vehicles/"+vehicle+"/command/set_charging_amps"))
.header("Accept", "application/json")
.header("Authorization", "Bearer " + accessToken)
.POST(HttpRequest.BodyPublishers.ofString("{\"charging_amps\":\""+amps+"\"}"))
.build();
JsonObject responseObject = sendRequest(request);
boolean result = responseObject.getJsonObject("response").getBoolean("result");
LOGGER.log(Level.INFO, "set charging amps to {0}. result = {1}", new Object[]{amps, result});
return result;
executeCommand("charging-set-amps "+amps);
return true;
}

public boolean setScheduledCharging(boolean enabled, int time) throws TeslaException {
if (accessToken == null) {
accessToken = getAccessToken(refreshToken);
if (enabled) {
executeCommand("charging-schedule "+time);
} else {
executeCommand("charging-schedule-cancel");
}
HttpRequest request = HttpRequest.newBuilder()
.timeout(Duration.ofSeconds(10))
.uri(URI.create(BASE + "/api/1/vehicles/"+vehicle+"/command/set_scheduled_charging"))
.header("Accept", "application/json")
.header("Authorization", "Bearer " + accessToken)
.POST(HttpRequest.BodyPublishers.ofString("{\"enable\":\""+enabled+"\", \"time\": "+time+"}"))
.build();
JsonObject responseObject = sendRequest(request);
boolean result = responseObject.getJsonObject("response").getBoolean("result");
LOGGER.log(Level.INFO, "set scheduled charging to {0} {1}. result = {2}", new Object[]{enabled, time, result});
return result;
return true;
}

public void wakeup() throws TeslaException {
if (accessToken == null) {
accessToken = getAccessToken(refreshToken);
}
HttpRequest request = HttpRequest.newBuilder()
.timeout(Duration.ofSeconds(10))
.uri(URI.create(BASE + "/api/1/vehicles/"+vehicle+"/wake_up"))
.header("Accept", "application/json")
.header("Authorization", "Bearer " + accessToken)
.POST(HttpRequest.BodyPublishers.ofString("{}"))
.build();
JsonObject responseObject = sendRequest(request);
LOGGER.log(Level.INFO, "wake up. result = {0}", responseObject);
executeCommand("wake");
// if (accessToken == null) {
// accessToken = getAccessToken(refreshToken);
// }
// HttpRequest request = HttpRequest.newBuilder()
// .timeout(Duration.ofSeconds(10))
// .uri(URI.create(BASE + "/api/1/vehicles/"+vehicle+"/wake_up"))
// .header("Accept", "application/json")
// .header("Authorization", "Bearer " + accessToken)
// .POST(HttpRequest.BodyPublishers.ofString("{}"))
// .build();
// JsonObject responseObject = sendRequest(request);
// LOGGER.log(Level.INFO, "wake up. result = {0}", responseObject);
}

public boolean stopCharging() throws TeslaException {
if (accessToken == null) {
accessToken = getAccessToken(refreshToken);
}
HttpRequest request = HttpRequest.newBuilder()
.timeout(Duration.ofSeconds(10))
.uri(URI.create(BASE + "/api/1/vehicles/"+vehicle+"/command/charge_stop"))
.header("Accept", "application/json")
.header("Authorization", "Bearer " + accessToken)
.POST(HttpRequest.BodyPublishers.ofString("{}"))
.build();
JsonObject responseObject = sendRequest(request);

boolean result = responseObject.getJsonObject("response").getBoolean("result");
LOGGER.log(Level.INFO, "stop charging. result = {0}", result);
return result;
executeCommand("charging-stop");
return true;
}

public boolean startCharging() throws TeslaException {
if (accessToken == null) {
accessToken = getAccessToken(refreshToken);
executeCommand("charging-start");
return true;
}

private void executeCommand(String command) throws TeslaException {
try {
ProcessBuilder builder = new ProcessBuilder("./tesla-control", "-ble", "-debug", command);
builder.directory(new File(sdkDir));
builder.environment().put("TESLA_KEY_NAME", keyName);
builder.environment().put("TESLA_TOKEN_NAME", tokenName);
builder.environment().put("TESLA_CACHE_FILE", cacheFile);
builder.environment().put("TESLA_VIN", vin);
Process p = builder.start();
int status = p.waitFor();
if (status != 0) {
String error = p.errorReader().lines().collect(Collectors.joining("\n"));
LOGGER.warning("Error sending BLE command "+error);
throw new TeslaException(408, "command returned "+status);
}
} catch (TeslaException e) {
throw e;
} catch (Exception e) {
LOGGER.log(Level.WARNING, "unexpected exception running command", e);
throw new TeslaException(0, "unexpected exception running command "+e);
}
HttpRequest request = HttpRequest.newBuilder()
.timeout(Duration.ofSeconds(10))
.uri(URI.create(BASE + "/api/1/vehicles/"+vehicle+"/command/charge_start"))
.header("Accept", "application/json")
.header("Authorization", "Bearer " + accessToken)
.POST(HttpRequest.BodyPublishers.ofString("{}"))
.build();
JsonObject responseObject = sendRequest(request);
boolean result = responseObject.getJsonObject("response").getBoolean("result");
LOGGER.log(Level.INFO, "start charging. result = {0}", result);
return result;
}

String getAccessToken(String refreshToken) throws TeslaException {
Expand Down
12 changes: 11 additions & 1 deletion src/main/java/homecontrol/impl/tesla/TeslaEV.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,22 @@ public class TeslaEV implements ElectricVehicle {

@ConfigProperty(name = "EVCHARGING_TESLA_VEHICLE")
String vehicle;
@ConfigProperty(name = "EVCHARGING_TESLA_VEHICLE_VIN")
String vin;
@ConfigProperty(name = "EVCHARGING_TESLA_KEY_NAME")
String keyName;
@ConfigProperty(name = "EVCHARGING_TESLA_TOKEN_NAME")
String tokenName;
@ConfigProperty(name = "EVCHARGING_TESLA_CACHE_FILE")
String cacheFile;
@ConfigProperty(name = "EVCHARGING_TESLA_COMMAND_SDK")
String sdkDir;
private TeslaClient teslaClient;
private EVState currentState;

@PostConstruct
public void postConstruct() {
teslaClient = new TeslaClient(refreshToken, vehicle);
teslaClient = new TeslaClient(refreshToken, vehicle, vin, keyName, tokenName, sdkDir, cacheFile);
}

@Override
Expand Down

0 comments on commit f255166

Please sign in to comment.