diff --git a/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/TeslaBindingConstants.java b/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/TeslaBindingConstants.java index 254dc508e..c75597000 100644 --- a/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/TeslaBindingConstants.java +++ b/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/TeslaBindingConstants.java @@ -109,6 +109,7 @@ public class TeslaBindingConstants { // 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"; diff --git a/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/handler/TeslaAccountHandler.java b/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/handler/TeslaAccountHandler.java index f7ac9fbc1..8f870c42e 100644 --- a/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/handler/TeslaAccountHandler.java +++ b/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/handler/TeslaAccountHandler.java @@ -71,7 +71,7 @@ import com.google.gson.JsonParser; */ 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") @@ -219,7 +219,7 @@ public class TeslaAccountHandler extends BaseBridgeHandler { 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; } @@ -308,7 +308,8 @@ public class TeslaAccountHandler extends BaseBridgeHandler { 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) { @@ -339,6 +340,16 @@ public class TeslaAccountHandler extends BaseBridgeHandler { 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; } @@ -445,16 +456,21 @@ public class TeslaAccountHandler extends BaseBridgeHandler { 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 @@ -463,7 +479,8 @@ public class TeslaAccountHandler extends BaseBridgeHandler { 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); } @@ -474,9 +491,9 @@ public class TeslaAccountHandler extends BaseBridgeHandler { } } - 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 diff --git a/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/handler/TeslaVehicleHandler.java b/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/handler/TeslaVehicleHandler.java index 83deb99b4..e7c89ca0c 100644 --- a/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/handler/TeslaVehicleHandler.java +++ b/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/handler/TeslaVehicleHandler.java @@ -112,6 +112,7 @@ public class TeslaVehicleHandler extends BaseThingHandler { protected ClimateState climateState; protected boolean allowWakeUp; + protected boolean allowWakeUpForCommands; protected boolean enableEvents = false; protected long lastTimeStamp; protected long apiIntervalTimestamp; @@ -151,6 +152,7 @@ public class TeslaVehicleHandler extends BaseThingHandler { 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); @@ -251,6 +253,11 @@ public class TeslaVehicleHandler extends BaseThingHandler { requestAllData(); } else { if (selector != null) { + if (!isAwake() && allowWakeUpForCommands) { + logger.debug("Waking vehicle to send command."); + wakeUp(); + setActive(); + } try { switch (selector) { case CHARGE_LIMIT_SOC: { @@ -449,8 +456,8 @@ public class TeslaVehicleHandler extends BaseThingHandler { } 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); } @@ -462,8 +469,8 @@ public class TeslaVehicleHandler extends BaseThingHandler { } 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); } @@ -471,8 +478,8 @@ public class TeslaVehicleHandler extends BaseThingHandler { } 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); } @@ -480,8 +487,8 @@ public class TeslaVehicleHandler extends BaseThingHandler { } 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); } @@ -731,7 +738,8 @@ public class TeslaVehicleHandler extends BaseThingHandler { 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"); @@ -965,23 +973,27 @@ public class TeslaVehicleHandler extends BaseThingHandler { } 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); } }; diff --git a/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/throttler/ScheduledChannelThrottler.java b/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/throttler/ScheduledChannelThrottler.java index ac56ecb0a..96201080d 100644 --- a/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/throttler/ScheduledChannelThrottler.java +++ b/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/throttler/ScheduledChannelThrottler.java @@ -21,7 +21,7 @@ import java.util.concurrent.TimeUnit; /** * 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 diff --git a/bundles/org.openhab.binding.tesla/src/main/resources/OH-INF/i18n/tesla.properties b/bundles/org.openhab.binding.tesla/src/main/resources/OH-INF/i18n/tesla.properties index 44bf04cc9..aa6777427 100644 --- a/bundles/org.openhab.binding.tesla/src/main/resources/OH-INF/i18n/tesla.properties +++ b/bundles/org.openhab.binding.tesla/src/main/resources/OH-INF/i18n/tesla.properties @@ -26,24 +26,32 @@ thing-type.config.tesla.account.username.label = Username 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 diff --git a/bundles/org.openhab.binding.tesla/src/main/resources/OH-INF/thing/model3.xml b/bundles/org.openhab.binding.tesla/src/main/resources/OH-INF/thing/model3.xml index 0566a8eee..55d7109df 100644 --- a/bundles/org.openhab.binding.tesla/src/main/resources/OH-INF/thing/model3.xml +++ b/bundles/org.openhab.binding.tesla/src/main/resources/OH-INF/thing/model3.xml @@ -134,6 +134,12 @@ Allows waking up the vehicle. Caution: This can result in huge vampire drain! + + false + + 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. + diff --git a/bundles/org.openhab.binding.tesla/src/main/resources/OH-INF/thing/models.xml b/bundles/org.openhab.binding.tesla/src/main/resources/OH-INF/thing/models.xml index 622a27b08..5fda08586 100644 --- a/bundles/org.openhab.binding.tesla/src/main/resources/OH-INF/thing/models.xml +++ b/bundles/org.openhab.binding.tesla/src/main/resources/OH-INF/thing/models.xml @@ -141,6 +141,12 @@ Allows waking up the vehicle. Caution: This can result in huge vampire drain! + + false + + 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. + diff --git a/bundles/org.openhab.binding.tesla/src/main/resources/OH-INF/thing/modelx.xml b/bundles/org.openhab.binding.tesla/src/main/resources/OH-INF/thing/modelx.xml index 4087941fa..b1753a842 100644 --- a/bundles/org.openhab.binding.tesla/src/main/resources/OH-INF/thing/modelx.xml +++ b/bundles/org.openhab.binding.tesla/src/main/resources/OH-INF/thing/modelx.xml @@ -141,6 +141,12 @@ Allows waking up the vehicle. Caution: This can result in huge vampire drain! + + false + + 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. + diff --git a/bundles/org.openhab.binding.tesla/src/main/resources/OH-INF/thing/modely.xml b/bundles/org.openhab.binding.tesla/src/main/resources/OH-INF/thing/modely.xml index 7724139c3..95e60569f 100644 --- a/bundles/org.openhab.binding.tesla/src/main/resources/OH-INF/thing/modely.xml +++ b/bundles/org.openhab.binding.tesla/src/main/resources/OH-INF/thing/modely.xml @@ -136,6 +136,12 @@ Allows waking up the vehicle. Caution: This can result in huge vampire drain! + + false + + 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. +