]> git.basschouten.com Git - openhab-addons.git/commitdiff
[tesla] Introduce "allowWakeUpForCommands" option (#12184)
authorKai Kreuzer <kai@openhab.org>
Wed, 2 Feb 2022 19:28:48 +0000 (20:28 +0100)
committerGitHub <noreply@github.com>
Wed, 2 Feb 2022 19:28:48 +0000 (20:28 +0100)
* Introduce "allowWakeUpForCommands" option

Signed-off-by: Kai Kreuzer <kai@openhab.org>
bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/TeslaBindingConstants.java
bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/handler/TeslaAccountHandler.java
bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/handler/TeslaVehicleHandler.java
bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/throttler/ScheduledChannelThrottler.java
bundles/org.openhab.binding.tesla/src/main/resources/OH-INF/i18n/tesla.properties
bundles/org.openhab.binding.tesla/src/main/resources/OH-INF/thing/model3.xml
bundles/org.openhab.binding.tesla/src/main/resources/OH-INF/thing/models.xml
bundles/org.openhab.binding.tesla/src/main/resources/OH-INF/thing/modelx.xml
bundles/org.openhab.binding.tesla/src/main/resources/OH-INF/thing/modely.xml

index 254dc508e3fedd7f4efa8cef5d7dc20435751eaf..c75597000468859d15d886eec176197bef27df20 100644 (file)
@@ -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";
index f7ac9fbc130d15af818a89d3301b43240fb3bc81..8f870c42e11b9c0ffab895b3791ca29460d333ab 100644 (file)
@@ -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
index 83deb99b422f5b0ae36400364290ac2bf1577935..e7c89ca0cfacb2a28ea98c72bd844c8097e7dc71 100644 (file)
@@ -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);
         }
     };
 
index ac56ecb0aac0aecda3997a47e4a3e7e962fe0d91..96201080dd629178e8f59fca334e12c8ed67596a 100644 (file)
@@ -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
index 44bf04cc92714da42407f12a60db8ecc83a761f7..aa6777427d0e46aeba392edaab378aaf87bb9037 100644 (file)
@@ -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
index 0566a8eee1dbb8980a490cceac314c3981890717..55d7109df20b8af09ff64e96a835a3648cb1a61e 100644 (file)
                                <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>
index 622a27b080e4221a34890f288f146bde42eb1de3..5fda08586b2f1ff539fc59a726ad6bebda5fe4f0 100644 (file)
                                <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>
index 4087941fa3df568f8e4bf87054a5604e47e67d8c..b1753a842fc9469f9823041ecd43d09ec372cfb7 100644 (file)
                                <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>
index 7724139c351468324eea9c1ff2362a32a1926153..95e60569f5ef9ab9d162690b75c3e40c220ebb10 100644 (file)
                                <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>