// thing configurations
public static final String CONFIG_ALLOWWAKEUP = "allowWakeup";
+ public static final String CONFIG_ALLOWWAKEUPFORCOMMANDS = "allowWakeupForCommands";
public static final String CONFIG_ENABLEEVENTS = "enableEvents";
public static final String CONFIG_REFRESHTOKEN = "refreshToken";
public static final String CONFIG_USERNAME = "username";
*/
public class TeslaAccountHandler extends BaseBridgeHandler {
- public static final int API_MAXIMUM_ERRORS_IN_INTERVAL = 2;
+ public static final int API_MAXIMUM_ERRORS_IN_INTERVAL = 3;
public static final int API_ERROR_INTERVAL_SECONDS = 15;
private static final int CONNECT_RETRY_INTERVAL = 15000;
private static final DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
Vehicle[] vehicleArray = gson.fromJson(jsonObject.getAsJsonArray("response"), Vehicle[].class);
for (Vehicle vehicle : vehicleArray) {
- String responseString = invokeAndParse(vehicle.id, VEHICLE_CONFIG, null, dataRequestTarget);
+ String responseString = invokeAndParse(vehicle.id, VEHICLE_CONFIG, null, dataRequestTarget, 0);
if (responseString == null || responseString.isBlank()) {
continue;
}
return new ThingStatusInfo(ThingStatus.ONLINE, ThingStatusDetail.NONE, null);
}
- protected String invokeAndParse(String vehicleId, String command, String payLoad, WebTarget target) {
+ protected String invokeAndParse(String vehicleId, String command, String payLoad, WebTarget target,
+ int noOfretries) {
logger.debug("Invoking: {}", command);
if (vehicleId != null) {
logger.debug("An error occurred while communicating with the vehicle during request {}: {}: {}",
command, (response != null) ? response.getStatus() : "",
(response != null) ? response.getStatusInfo().getReasonPhrase() : "No Response");
+ if (response.getStatus() == 408 && noOfretries > 0) {
+ try {
+ // we give the vehicle a moment to wake up and try the request again
+ Thread.sleep(TimeUnit.SECONDS.toMillis(API_ERROR_INTERVAL_SECONDS));
+ logger.debug("Retrying to send the command {}.", command);
+ return invokeAndParse(vehicleId, command, payLoad, target, noOfretries - 1);
+ } catch (InterruptedException e) {
+ return null;
+ }
+ }
return null;
}
protected class Request implements Runnable {
+ private static final int NO_OF_RETRIES = 3;
+
private TeslaVehicleHandler handler;
private String request;
private String payLoad;
private WebTarget target;
+ private boolean allowWakeUpForCommands;
- public Request(TeslaVehicleHandler handler, String request, String payLoad, WebTarget target) {
+ public Request(TeslaVehicleHandler handler, String request, String payLoad, WebTarget target,
+ boolean allowWakeUpForCommands) {
this.handler = handler;
this.request = request;
this.payLoad = payLoad;
this.target = target;
+ this.allowWakeUpForCommands = allowWakeUpForCommands;
}
@Override
String result = "";
if (getThing().getStatus() == ThingStatus.ONLINE) {
- result = invokeAndParse(handler.getVehicleId(), request, payLoad, target);
+ result = invokeAndParse(handler.getVehicleId(), request, payLoad, target,
+ allowWakeUpForCommands ? NO_OF_RETRIES : 0);
if (result != null && !"".equals(result)) {
handler.parseAndUpdate(request, payLoad, result);
}
}
}
- public Request newRequest(TeslaVehicleHandler teslaVehicleHandler, String command, String payLoad,
- WebTarget target) {
- return new Request(teslaVehicleHandler, command, payLoad, target);
+ public Request newRequest(TeslaVehicleHandler teslaVehicleHandler, String command, String payLoad, WebTarget target,
+ boolean allowWakeUpForCommands) {
+ return new Request(teslaVehicleHandler, command, payLoad, target, allowWakeUpForCommands);
}
@Override
protected ClimateState climateState;
protected boolean allowWakeUp;
+ protected boolean allowWakeUpForCommands;
protected boolean enableEvents = false;
protected long lastTimeStamp;
protected long apiIntervalTimestamp;
logger.trace("Initializing the Tesla handler for {}", getThing().getUID());
updateStatus(ThingStatus.UNKNOWN);
allowWakeUp = (boolean) getConfig().get(TeslaBindingConstants.CONFIG_ALLOWWAKEUP);
+ allowWakeUpForCommands = (boolean) getConfig().get(TeslaBindingConstants.CONFIG_ALLOWWAKEUPFORCOMMANDS);
// the streaming API seems to be broken - let's keep the code, if it comes back one day
// enableEvents = (boolean) getConfig().get(TeslaBindingConstants.CONFIG_ENABLEEVENTS);
requestAllData();
} else {
if (selector != null) {
+ if (!isAwake() && allowWakeUpForCommands) {
+ logger.debug("Waking vehicle to send command.");
+ wakeUp();
+ setActive();
+ }
try {
switch (selector) {
case CHARGE_LIMIT_SOC: {
}
public void sendCommand(String command, String payLoad, WebTarget target) {
- if (command.equals(COMMAND_WAKE_UP) || isAwake()) {
- Request request = account.newRequest(this, command, payLoad, target);
+ if (command.equals(COMMAND_WAKE_UP) || isAwake() || allowWakeUpForCommands) {
+ Request request = account.newRequest(this, command, payLoad, target, allowWakeUpForCommands);
if (stateThrottler != null) {
stateThrottler.submit(COMMAND_THROTTLE, request);
}
}
public void sendCommand(String command, String payLoad) {
- if (command.equals(COMMAND_WAKE_UP) || isAwake()) {
- Request request = account.newRequest(this, command, payLoad, account.commandTarget);
+ if (command.equals(COMMAND_WAKE_UP) || isAwake() || allowWakeUpForCommands) {
+ Request request = account.newRequest(this, command, payLoad, account.commandTarget, allowWakeUpForCommands);
if (stateThrottler != null) {
stateThrottler.submit(COMMAND_THROTTLE, request);
}
}
public void sendCommand(String command, WebTarget target) {
- if (command.equals(COMMAND_WAKE_UP) || isAwake()) {
- Request request = account.newRequest(this, command, "{}", target);
+ if (command.equals(COMMAND_WAKE_UP) || isAwake() || allowWakeUpForCommands) {
+ Request request = account.newRequest(this, command, "{}", target, allowWakeUpForCommands);
if (stateThrottler != null) {
stateThrottler.submit(COMMAND_THROTTLE, request);
}
}
public void requestData(String command, String payLoad) {
- if (command.equals(COMMAND_WAKE_UP) || isAwake()) {
- Request request = account.newRequest(this, command, payLoad, account.dataRequestTarget);
+ if (command.equals(COMMAND_WAKE_UP) || isAwake() || allowWakeUpForCommands) {
+ Request request = account.newRequest(this, command, payLoad, account.dataRequestTarget, false);
if (stateThrottler != null) {
stateThrottler.submit(DATA_THROTTLE, request);
}
Response response = account.vehiclesTarget.request(MediaType.APPLICATION_JSON_TYPE)
.header("Authorization", authHeader).get();
- logger.debug("Querying the vehicle : Response : {}:{}", response.getStatus(), response.getStatusInfo());
+ logger.debug("Querying the vehicle, response : {}, {}", response.getStatus(),
+ response.getStatusInfo().getReasonPhrase());
if (!checkResponse(response, true)) {
logger.error("An error occurred while querying the vehicle");
}
protected Runnable slowStateRunnable = () -> {
- queryVehicleAndUpdate();
+ try {
+ queryVehicleAndUpdate();
- boolean allowQuery = allowQuery();
+ boolean allowQuery = allowQuery();
- if (allowQuery) {
- requestData(CHARGE_STATE);
- requestData(CLIMATE_STATE);
- requestData(GUI_STATE);
- queryVehicle(MOBILE_ENABLED_STATE);
- } else {
- if (allowWakeUp) {
- wakeUp();
+ if (allowQuery) {
+ requestData(CHARGE_STATE);
+ requestData(CLIMATE_STATE);
+ requestData(GUI_STATE);
+ queryVehicle(MOBILE_ENABLED_STATE);
} else {
- if (isAwake()) {
- logger.debug("Vehicle is neither charging nor moving, skipping updates to allow it to sleep");
+ if (allowWakeUp) {
+ wakeUp();
+ } else {
+ if (isAwake()) {
+ logger.debug("Vehicle is neither charging nor moving, skipping updates to allow it to sleep");
+ }
}
}
+ } catch (Exception e) {
+ logger.warn("Exception occurred in slowStateRunnable", e);
}
};
/**
* The {@link ScheduledChannelThrottler} implements a throttler that maintains a
- * single execution rates, and does not maintains order of calls (thus have to
+ * single execution rates, and does not maintain order of calls (thus has to
* start from back rather than try to insert things in middle)
*
* @author Karel Goderis - Initial contribution
thing-type.config.tesla.account.username.description = Username for the Tesla Remote Service, e.g email address.
thing-type.config.tesla.model3.allowWakeup.label = Allow Wake-Up
thing-type.config.tesla.model3.allowWakeup.description = Allows waking up the vehicle. Caution: This can result in huge vampire drain!
+thing-type.config.tesla.model3.allowWakeupForCommands.label = Allow Wake-Up For Commands
+thing-type.config.tesla.model3.allowWakeupForCommands.description = Allows waking up the vehicle, when commands are sent to it. Execution of commands will be delayed in this case and you could cause the vehicle to stay awake very long.
thing-type.config.tesla.model3.valetpin.label = Valet PIN
thing-type.config.tesla.model3.valetpin.description = PIN to use when enabling Valet Mode
thing-type.config.tesla.model3.vin.label = Vehicle Identification Number
thing-type.config.tesla.model3.vin.description = VIN of the vehicle
thing-type.config.tesla.models.allowWakeup.label = Allow Wake-Up
thing-type.config.tesla.models.allowWakeup.description = Allows waking up the vehicle. Caution: This can result in huge vampire drain!
+thing-type.config.tesla.models.allowWakeupForCommands.label = Allow Wake-Up For Commands
+thing-type.config.tesla.models.allowWakeupForCommands.description = Allows waking up the vehicle, when commands are sent to it. Execution of commands will be delayed in this case and you could cause the vehicle to stay awake very long.
thing-type.config.tesla.models.valetpin.label = Valet PIN
thing-type.config.tesla.models.valetpin.description = PIN to use when enabling Valet Mode
thing-type.config.tesla.models.vin.label = Vehicle Identification Number
thing-type.config.tesla.models.vin.description = VIN of the vehicle
thing-type.config.tesla.modelx.allowWakeup.label = Allow Wake-Up
thing-type.config.tesla.modelx.allowWakeup.description = Allows waking up the vehicle. Caution: This can result in huge vampire drain!
+thing-type.config.tesla.modelx.allowWakeupForCommands.label = Allow Wake-Up For Commands
+thing-type.config.tesla.modelx.allowWakeupForCommands.description = Allows waking up the vehicle, when commands are sent to it. Execution of commands will be delayed in this case and you could cause the vehicle to stay awake very long.
thing-type.config.tesla.modelx.valetpin.label = Valet PIN
thing-type.config.tesla.modelx.valetpin.description = PIN to use when enabling Valet Mode
thing-type.config.tesla.modelx.vin.label = Vehicle Identification Number
thing-type.config.tesla.modelx.vin.description = VIN of the vehicle
thing-type.config.tesla.modely.allowWakeup.label = Allow Wake-Up
thing-type.config.tesla.modely.allowWakeup.description = Allows waking up the vehicle. Caution: This can result in huge vampire drain!
+thing-type.config.tesla.modely.allowWakeupForCommands.label = Allow Wake-Up For Commands
+thing-type.config.tesla.modely.allowWakeupForCommands.description = Allows waking up the vehicle, when commands are sent to it. Execution of commands will be delayed in this case and you could cause the vehicle to stay awake very long.
thing-type.config.tesla.modely.valetpin.label = Valet PIN
thing-type.config.tesla.modely.valetpin.description = PIN to use when enabling Valet Mode
thing-type.config.tesla.modely.vin.label = Vehicle Identification Number
<label>Allow Wake-Up</label>
<description>Allows waking up the vehicle. Caution: This can result in huge vampire drain!</description>
</parameter>
+ <parameter name="allowWakeupForCommands" type="boolean" required="false">
+ <default>false</default>
+ <label>Allow Wake-Up For Commands</label>
+ <description>Allows waking up the vehicle, when commands are sent to it. Execution of commands will be delayed in
+ this case and you could cause the vehicle to stay awake very long.</description>
+ </parameter>
</config-description>
</thing-type>
<label>Allow Wake-Up</label>
<description>Allows waking up the vehicle. Caution: This can result in huge vampire drain!</description>
</parameter>
+ <parameter name="allowWakeupForCommands" type="boolean" required="false">
+ <default>false</default>
+ <label>Allow Wake-Up For Commands</label>
+ <description>Allows waking up the vehicle, when commands are sent to it. Execution of commands will be delayed in
+ this case and you could cause the vehicle to stay awake very long.</description>
+ </parameter>
</config-description>
</thing-type>
<label>Allow Wake-Up</label>
<description>Allows waking up the vehicle. Caution: This can result in huge vampire drain!</description>
</parameter>
+ <parameter name="allowWakeupForCommands" type="boolean" required="false">
+ <default>false</default>
+ <label>Allow Wake-Up For Commands</label>
+ <description>Allows waking up the vehicle, when commands are sent to it. Execution of commands will be delayed in
+ this case and you could cause the vehicle to stay awake very long.</description>
+ </parameter>
</config-description>
</thing-type>
<label>Allow Wake-Up</label>
<description>Allows waking up the vehicle. Caution: This can result in huge vampire drain!</description>
</parameter>
+ <parameter name="allowWakeupForCommands" type="boolean" required="false">
+ <default>false</default>
+ <label>Allow Wake-Up For Commands</label>
+ <description>Allows waking up the vehicle, when commands are sent to it. Execution of commands will be delayed in
+ this case and you could cause the vehicle to stay awake very long.</description>
+ </parameter>
</config-description>
</thing-type>