mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-25 14:55:55 +01:00
[tesla] Options to control polling frequency and sleep (#13337)
* Options to control polling frequency and sleep mode * Update documentation * Fix request token expiration calculation and additional logging for tokens Signed-off-by: Bill Forsyth <git@billforsyth.net>
This commit is contained in:
parent
45bf7aeeda
commit
39e2a29bcf
@ -41,16 +41,35 @@ Please note that we in general consider it dangerous to enter your credentials i
|
||||
When using one of such apps, simply copy and paste the received refresh token into the account configuration.
|
||||
|
||||
|
||||
## Thing Configuration
|
||||
## Thing Configuration Parameters
|
||||
|
||||
The vehicle Thing requires the vehicle's VIN as a configuration parameter `vin`.
|
||||
|
||||
Additionally, the optional boolean parameter `allowWakeup` can be set.
|
||||
This determines whether openHAB is allowed to wake up the vehicle in order to retrieve data from it.
|
||||
Additionally, the follow optional parameters may be defined.
|
||||
|
||||
| Parameter Name | Label | Default Value | Description |
|
||||
|------------------------|----------------------------|---------------|------------------------------------------------------------------------------|
|
||||
| valetpin | Valet PIN | false | PIN to use when enabling Valet Mode |
|
||||
| allowWakeupForCommands | Allow Wake-Up For Commands | false | Wake up the vehicle to send commands. May cause vehicle to stay awake |
|
||||
|
||||
|
||||
For further flexibility and experimentation, the following advanced parameters may also be set.
|
||||
|
||||
| Parameter Name | Label | Default Value | Description |
|
||||
|-----------------------------|------------------------------------------------|---------------|----------------------------------------------------------------------------------------------------|
|
||||
| allowWakeup | Allow Wake-Up | false | Allows waking up the vehicle to retrieve data. See caution below |
|
||||
| enableEvents | Enable Events | false | Enable the event stream for the vehicle. See note below |
|
||||
| inactivity | Inactivity Interval | 5 | The inactivity period in minutes after which the binding stops for 20 minutes to let the car sleep |
|
||||
| useDriveState | Use Drive State for Inactivity | false | Use the drive state instead of location to determine vehicle inactivity |
|
||||
| useAdvancedStatesForPolling | Use Console Modes and Occupancy for Inactivity | false | Use these states to help continue the fast polling of the API |
|
||||
|
||||
`allowWakeup` should be used with caution as this determines whether openHAB is allowed to wake up the vehicle in order to retrieve data from it.
|
||||
This setting is not recommended as it will result in a significant vampire drain (i.e. energy consumption although the vehicle is parking).
|
||||
|
||||
In addition, the optional boolean parameter `enableEvents` can be set.
|
||||
By doing so, events streamed by the Tesla back-end system will be captured and processed, providing near real-time updates of some key variables generated by the vehicle.
|
||||
`enableEvents` captures and processes data in near real-time for key variables by enabling events streamed by the Tesla back-end system.
|
||||
|
||||
`inactivity` setting is ignored and will always be five minutes if homelink is available (car is at home)
|
||||
|
||||
|
||||
## Channels
|
||||
|
||||
@ -191,60 +210,186 @@ Bridge tesla:account:myaccount "My Tesla Account" [ refreshToken="xxxx" ] {
|
||||
demo.items:
|
||||
|
||||
```
|
||||
Switch TeslaCharge {channel="tesla:model3:myaccount:mycar:charge"}
|
||||
Location TeslaLocation {channel="tesla:model3:myaccount:mycar:location"}
|
||||
Dimmer TeslaChargeLimit {channel="tesla:model3:myaccount:mycar:chargelimit"}
|
||||
String TeslaChargeRate {channel="tesla:model3:myaccount:mycar:chargerate"}
|
||||
String TeslaChargingState {channel="tesla:model3:myaccount:mycar:chargingstate"}
|
||||
Number TeslaTimeToFullCharge {channel="tesla:model3:myaccount:mycar:timetofullcharge"}
|
||||
Number TeslaChargerPower {channel="tesla:model3:myaccount:mycar:chargerpower"}
|
||||
DateTime TeslaScheduledChargingStart {channel="tesla:model3:myaccount:mycar:scheduledchargingstart"}
|
||||
Dimmer TeslaSoC {channel="tesla:model3:myaccount:mycar:soc"}
|
||||
Number:Speed TeslaSpeed {channel="tesla:model3:myaccount:mycar:speed"}
|
||||
String TeslaState {channel="tesla:model3:myaccount:mycar:state"}
|
||||
Number TeslaPower {channel="tesla:model3:myaccount:mycar:power"}
|
||||
Number:Temperature TeslaInsideTemperature {channel="tesla:model3:myaccount:mycar:insidetemp"}
|
||||
Number:Temperature TeslaOutsideTemperature {channel="tesla:model3:myaccount:mycar:outsidetemp"}
|
||||
Switch TeslaAutoconditioning {channel="tesla:model3:myaccount:mycar:autoconditioning"}
|
||||
Number:Temperature TeslaTemperature {channel="tesla:model3:myaccount:mycar:temperature"}
|
||||
String TeslaShiftState {channel="tesla:model3:myaccount:mycar:shiftstate"}
|
||||
Number TeslaBatteryCurrent {channel="tesla:model3:myaccount:mycar:batterycurrent"}
|
||||
Number TeslaBatteryLevel {channel="tesla:model3:myaccount:mycar:batterylevel"}
|
||||
DateTime TeslaEventstamp {channel="tesla:model3:myaccount:mycar:eventstamp"}
|
||||
Number:Length TeslaOdometer {channel="tesla:model3:myaccount:mycar:odometer"}
|
||||
Number TeslaHeading {channel="tesla:model3:myaccount:mycar:heading"}
|
||||
DateTime TeslaGPSStamp {channel="tesla:model3:myaccount:mycar:gpstimestamp"}
|
||||
DateTime TeslaEventstamp {channel="model3:myaccount:mycar:eventstamp"}
|
||||
String TeslaState {channel="model3:myaccount:mycar:state"}
|
||||
Number TeslaSpeed {channel="model3:myaccount:mycar:speed"}
|
||||
String TeslaShiftState {channel="model3:myaccount:mycar:shiftstate"}
|
||||
Number TeslaOdometer {channel="model3:myaccount:mycar:odometer"}
|
||||
Number TeslaRange {channel="model3:myaccount:mycar:range"}
|
||||
|
||||
Number TeslaBatteryLevel {channel="model3:myaccount:mycar:batterylevel"}
|
||||
Number TeslaPower {channel="model3:myaccount:mycar:power"}
|
||||
Number TeslaBatteryCurrent {channel="model3:myaccount:mycar:batterycurrent"}
|
||||
Number TeslaBatteryRange {channel="model3:myaccount:mycar:batteryrange"}
|
||||
Number TeslaEstBatteryRange {channel="model3:myaccount:mycar:estimatedbatteryrange"}
|
||||
Number TeslaIdealBatteryRange {channel="model3:myaccount:mycar:idealbatteryrange"}
|
||||
Number TeslaUsableBatteryLevel {channel="model3:myaccount:mycar:usablebatterylevel"}
|
||||
Switch TeslaPreconditioning {channel="model3:myaccount:mycar:preconditioning"}
|
||||
|
||||
Switch TeslaCharge {channel="model3:myaccount:mycar:charge"}
|
||||
Switch TeslaChargeToMax {channel="model3:myaccount:mycar:chargetomax"}
|
||||
|
||||
Dimmer TeslaChargeLimit {channel="model3:myaccount:mycar:chargelimit"}
|
||||
Number TeslaChargeRate {channel="model3:myaccount:mycar:chargerate"}
|
||||
String TeslaChargingState {channel="model3:myaccount:mycar:chargingstate"}
|
||||
Number TeslaChargerPower {channel="model3:myaccount:mycar:chargerpower"}
|
||||
Number TeslaTimeToFullCharge {channel="model3:myaccount:mycar:timetofullcharge"}
|
||||
Number TeslaMaxCharges {channel="model3:myaccount:mycar:maxcharges"}
|
||||
|
||||
Number TeslaChargerVoltage {channel="model3:myaccount:mycar:chargervoltage"}
|
||||
Number TeslaChargerPower {channel="model3:myaccount:mycar:chargerpower"}
|
||||
Number TeslaChargerCurrent {channel="model3:myaccount:mycar:chargercurrent"}
|
||||
|
||||
DateTime TeslaScheduledChargingStart {channel="model3:myaccount:mycar:scheduledchargingstart"}
|
||||
Dimmer TeslaSoC {channel="model3:myaccount:mycar:soc"}
|
||||
|
||||
Switch TeslaDoorLock {channel="model3:myaccount:mycar:doorlock"}
|
||||
Switch TeslaHorn {channel="model3:myaccount:mycar:honkhorn"}
|
||||
Switch TeslaStart {channel="model3:myaccount:mycar:remotestart"}
|
||||
Switch TeslaSentry {channel="model3:myaccount:mycar:sentrymode"}
|
||||
Switch TeslaLights {channel="model3:myaccount:mycar:flashlights"}
|
||||
Switch TeslaValet {channel="model3:myaccount:mycar:valetmode"}
|
||||
|
||||
Switch TeslaWakeup {channel="model3:myaccount:mycar:wakeup"}
|
||||
|
||||
Switch TeslaBatteryHeater {channel="model3:myaccount:mycar:batteryheater"}
|
||||
Switch TeslaFrontDefrost {channel="model3:myaccount:mycar:frontdefroster"}
|
||||
Switch TeslaRearDefrost {channel="model3:myaccount:mycar:reardefroster"}
|
||||
Switch TeslaLeftSeatHeater {channel="model3:myaccount:mycar:leftseatheater"}
|
||||
Switch TeslaRightSeatHeater {channel="model3:myaccount:mycar:rightseatheater"}
|
||||
|
||||
Switch TeslaHomelink {channel="model3:myaccount:mycar:homelink"}
|
||||
Location TeslaLocation {channel="model3:myaccount:mycar:location"}
|
||||
Number TeslaHeading {channel="model3:myaccount:mycar:heading"}
|
||||
DateTime TeslaLocationTime {channel="model3:myaccount:mycar:gpstimestamp"}
|
||||
|
||||
Switch TeslaAutoconditioning {channel="model3:myaccount:mycar:autoconditioning"}
|
||||
Number:Temperature TeslaTemperature {channel="model3:myaccount:mycar:temperature"}
|
||||
Number:Temperature TeslaTemperatureCombined {channel="model3:myaccount:mycar:combinedtemp"}
|
||||
Number:Temperature TeslaInsideTemperature {channel="model3:myaccount:mycar:insidetemp"}
|
||||
Number:Temperature TeslaOutsideTemperature {channel="model3:myaccount:mycar:outsidetemp"}
|
||||
```
|
||||
|
||||
demo.sitemap:
|
||||
|
||||
```
|
||||
sitemap demo label="Main Menu"
|
||||
sitemap main label="Main"
|
||||
{
|
||||
Text label="Car" {
|
||||
Text label="Drive" {
|
||||
Text item=TeslaEventstamp label="Last Event Timestamp [%1$td.%1$tm.%1$tY %1$tT]"
|
||||
Text item=TeslaState label="State [%s]"
|
||||
Text item=TeslaSpeed label="Speed [%.1f]"
|
||||
Text item=TeslaShiftState label="Shift State [%s]"
|
||||
Text item=TeslaOdometer label="Odometer [%.1f km]"
|
||||
}
|
||||
Text label="Climate" {
|
||||
Switch item=TeslaAutoconditioning label="Auto Conditioning" mappings=[ON=ON, OFF=OFF ]
|
||||
Setpoint item=TeslaTemperature step=0.5 minValue=18 maxValue=34 label="Auto Conditioning Temperature [%.1f °C]" icon="temperature"
|
||||
Text item=TeslaInsideTemperature label="Inside Temperature [%.1f]"
|
||||
}
|
||||
Text label="Power" {
|
||||
Text item=TeslaBatteryCurrent label="Current [%.1f]"
|
||||
}
|
||||
Text item=TeslaSoC {
|
||||
Switch item=TeslaCharge label="Charge" mappings=[ON=ON, OFF=OFF ]
|
||||
Slider item=TeslaChargeLimit label="Charge Limit [%.1f]"
|
||||
Text item=TeslaChargingState label="Charging State [%s]"
|
||||
Text item=TeslaChargeRate label="Charge Rate [%s]"
|
||||
Text item=TeslaScheduledChargingStart label="Charging Start [%1$td.%1$tm.%1$tY %1$tT]"
|
||||
Text item=TeslaTimeToFullCharge label="Time To Full Charge [%.1f hours]"
|
||||
}
|
||||
}
|
||||
Text item=TeslaUsableBatteryLevel label="Car" icon="tesla" valuecolor=[<=20="red",>60="green"]
|
||||
{
|
||||
Frame
|
||||
{
|
||||
Text item=TeslaEventstamp icon="time"
|
||||
Text item=TeslaState label="State [%s]" icon=""
|
||||
Text item=TeslaHomelink label="Homelink Available[%s]" icon=""
|
||||
Text item=TeslaDistance
|
||||
Text item=TeslaSpeed label="Speed [%.1f]"
|
||||
Text item=TeslaShiftState label="Shift State [%s]" icon=""
|
||||
Text item=nTeslaShiftState
|
||||
Text item=TeslaOdometer label="Odometer [%.1f miles]"
|
||||
Text item=TeslaRange
|
||||
}
|
||||
Frame
|
||||
{
|
||||
Switch item=TeslaAutoconditioning label="Enable Heat or AC"
|
||||
Setpoint item=TeslaTemperature step=0.5 minValue=65 maxValue=78 label="Auto Conditioning Temperature [%.1f °F]"
|
||||
Text item=TeslaInsideTemperature label="Inside Temperature [%.1f °F]" valuecolor=[<=32="blue",>95="red"]
|
||||
Text item=TeslaOutsideTemperature label="Outside Temperature [%.1f °F]" valuecolor=[<=32="blue",>95="red"]
|
||||
}
|
||||
Frame
|
||||
{
|
||||
Text item=TeslaBatteryLevel
|
||||
Text item=TeslaUsableBatteryLevel
|
||||
Text item=TeslaPower
|
||||
Text item=TeslaBatteryCurrent label="Current [%.1f]"
|
||||
Text item=TeslaBatteryRange label="Battery Range [%.1f miles]"
|
||||
Text item=TeslaEstBatteryRange label="Battery Est Range [%.1f miles]"
|
||||
Text item=TeslaIdealBatteryRange label="Battery Ideal Range [%.1f miles]"
|
||||
}
|
||||
Frame
|
||||
{
|
||||
Switch item=TeslaCharge label="Charge"
|
||||
Slider item=TeslaChargeLimit label="Charge Limit [%.1f]"
|
||||
Text item=TeslaChargingState label="Charging State [%s]" icon=""
|
||||
Text item=TeslaTimeToFullCharge label="Time To Full Charge [%.1f hours]"
|
||||
Text item=TeslaPreconditioning label="Preconditioning [%s]" icon=""
|
||||
Text item=TeslaChargeRate label="Charge Rate [%d miles/hr]"
|
||||
Text item=TeslaScheduledChargingStart icon="time"
|
||||
Text item=TeslaChargerVoltage label="Charge Voltage [%.1f V]"
|
||||
Text item=TeslaChargerPower label="Charge Power [%.1f kW]"
|
||||
Text item=TeslaChargerCurrent label="Charge Current [%.1f A]"
|
||||
Text item=TeslaChargeToMax label="Charge To Max [%s]" icon=""
|
||||
Text item=TeslaMaxCharges label="Consec Max Charge[%d]"
|
||||
}
|
||||
Frame
|
||||
{
|
||||
Switch item=TeslaWakeup label="Wakeup the Car"
|
||||
}
|
||||
Frame
|
||||
{
|
||||
Switch item=TeslaDoorLock label="Doorlock"
|
||||
Switch item=TeslaHorn label="Horn"
|
||||
Switch item=TeslaLights label="Lights"
|
||||
Switch item=TeslaStart label="Remote Start"
|
||||
Switch item=TeslaValet label="Valet Mode"
|
||||
Switch item=TeslaSentry label="Sentry Mode"
|
||||
|
||||
Switch item=TeslaBatteryHeater label="Battery Heater"
|
||||
Switch item=TeslaFrontDefrost label="Defrost Front"
|
||||
Switch item=TeslaRearDefrost label="Defrost Rear"
|
||||
Switch item=TeslaLeftSeatHeater label="Seat Heat Left"
|
||||
Switch item=TeslaRightSeatHeater label="Seat Heat Right"
|
||||
}
|
||||
Frame
|
||||
{
|
||||
Switch label="State" item=nTeslaState_chart icon=line mappings=[0="Hide", 1="Hour", 2="Day", 3="Week", 4="Month"]
|
||||
Chart item=nTeslaState period=h refresh=30000 visibility=[nTeslaState_chart==1]
|
||||
Chart item=nTeslaState period=D refresh=30000 visibility=[nTeslaState_chart==2]
|
||||
Chart item=nTeslaState period=W refresh=30000 visibility=[nTeslaState_chart==3]
|
||||
Chart item=nTeslaState period=M refresh=30000 visibility=[nTeslaState_chart==4]
|
||||
}
|
||||
Frame
|
||||
{
|
||||
Switch label="Battery" item=TeslaBatteryLevel_chart icon=line mappings=[0="Hide", 1="Hour", 2="Day", 3="Week", 4="Month"]
|
||||
Chart item=TeslaUsableBatteryLevel period=h refresh=30000 visibility=[TeslaBatteryLevel_chart==1]
|
||||
Chart item=TeslaUsableBatteryLevel period=D refresh=30000 visibility=[TeslaBatteryLevel_chart==2]
|
||||
Chart item=TeslaUsableBatteryLevel period=W refresh=30000 visibility=[TeslaBatteryLevel_chart==3]
|
||||
Chart item=TeslaUsableBatteryLevel period=M refresh=30000 visibility=[TeslaBatteryLevel_chart==4]
|
||||
}
|
||||
Frame
|
||||
{
|
||||
Mapview item=TeslaLocation height=10 icon=location
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
demo.rule (for graphing online status in sitemap above)
|
||||
|
||||
```
|
||||
rule "Tesla State Changed"
|
||||
when
|
||||
Item TeslaState changed
|
||||
|
||||
then
|
||||
if (previousState == NULL) return;
|
||||
switch (TeslaState.state) {
|
||||
case "online" : {
|
||||
nTeslaState.postUpdate(1)
|
||||
}
|
||||
case "asleep" : {
|
||||
nTeslaState.postUpdate(0)
|
||||
}
|
||||
case "offline" : {
|
||||
nTeslaState.postUpdate(-0.5)
|
||||
}
|
||||
case "waking" : {
|
||||
nTeslaState.postUpdate(0.5)
|
||||
}
|
||||
case "unknown" : {
|
||||
nTeslaState.postUpdate(-1)
|
||||
}
|
||||
|
||||
}
|
||||
end
|
||||
```
|
||||
|
@ -112,4 +112,7 @@ public class TeslaBindingConstants {
|
||||
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_INACTIVITY = "inactivity";
|
||||
public static final String CONFIG_USEDRIVESTATE = "useDriveState";
|
||||
public static final String CONFIG_USEDADVANCEDSTATES = "useAdvancedStatesForPolling";
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ public class TeslaAccountHandler extends BaseBridgeHandler {
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
logger.trace("Initializing the Tesla account handler for {}", this.getStorageKey());
|
||||
logger.debug("Initializing the Tesla account handler for {}", this.getStorageKey());
|
||||
|
||||
updateStatus(ThingStatus.UNKNOWN);
|
||||
|
||||
@ -129,7 +129,7 @@ public class TeslaAccountHandler extends BaseBridgeHandler {
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
logger.trace("Disposing the Tesla account handler for {}", getThing().getUID());
|
||||
logger.debug("Disposing the Tesla account handler for {}", getThing().getUID());
|
||||
|
||||
lock.lock();
|
||||
try {
|
||||
@ -256,16 +256,19 @@ public class TeslaAccountHandler extends BaseBridgeHandler {
|
||||
TokenResponse token = logonToken;
|
||||
|
||||
boolean hasExpired = true;
|
||||
logger.debug("Current authentication time {}", dateFormatter.format(Instant.now()));
|
||||
|
||||
if (token != null) {
|
||||
Instant tokenCreationInstant = Instant.ofEpochMilli(token.created_at * 1000);
|
||||
logger.debug("Found a request token created at {}", dateFormatter.format(tokenCreationInstant));
|
||||
Instant tokenExpiresInstant = Instant.ofEpochMilli(token.created_at * 1000 + 60 * token.expires_in);
|
||||
Instant tokenExpiresInstant = Instant.ofEpochMilli((token.created_at + token.expires_in) * 1000);
|
||||
logger.debug("Found a request token from {}", dateFormatter.format(tokenCreationInstant));
|
||||
logger.debug("Access token expiration time {}", dateFormatter.format(tokenExpiresInstant));
|
||||
|
||||
if (tokenExpiresInstant.isBefore(Instant.now())) {
|
||||
logger.debug("The token has expired at {}", dateFormatter.format(tokenExpiresInstant));
|
||||
logger.debug("The access token has expired");
|
||||
hasExpired = true;
|
||||
} else {
|
||||
logger.debug("The access token has not expired yet");
|
||||
hasExpired = false;
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,8 @@ package org.openhab.binding.tesla.internal.handler;
|
||||
import static org.openhab.binding.tesla.internal.TeslaBindingConstants.*;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
@ -44,6 +46,8 @@ public class TeslaSSOHandler {
|
||||
private final HttpClient httpClient;
|
||||
private final Gson gson = new Gson();
|
||||
private final Logger logger = LoggerFactory.getLogger(TeslaSSOHandler.class);
|
||||
private static final DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
|
||||
.withZone(ZoneId.systemDefault());
|
||||
|
||||
public TeslaSSOHandler(HttpClient httpClient) {
|
||||
this.httpClient = httpClient;
|
||||
@ -70,6 +74,8 @@ public class TeslaSSOHandler {
|
||||
|
||||
if (tokenResponse != null && tokenResponse.access_token != null && !tokenResponse.access_token.isEmpty()) {
|
||||
tokenResponse.created_at = Instant.now().getEpochSecond();
|
||||
logger.debug("Access token expires in {} seconds at {}", tokenResponse.expires_in, dateFormatter
|
||||
.format(Instant.ofEpochMilli((tokenResponse.created_at + tokenResponse.expires_in) * 1000)));
|
||||
return tokenResponse;
|
||||
} else {
|
||||
logger.debug("An error occurred while exchanging SSO auth token for API access token.");
|
||||
|
@ -89,7 +89,8 @@ public class TeslaVehicleHandler extends BaseThingHandler {
|
||||
private static final int FAST_STATUS_REFRESH_INTERVAL = 15000;
|
||||
private static final int SLOW_STATUS_REFRESH_INTERVAL = 60000;
|
||||
private static final int API_SLEEP_INTERVAL_MINUTES = 20;
|
||||
private static final int MOVE_THRESHOLD_INTERVAL_MINUTES = 5;
|
||||
private static final int MOVE_THRESHOLD_INTERVAL_MINUTES_DEFAULT = 5;
|
||||
private static final int THRESHOLD_INTERVAL_FOR_ADVANCED_MINUTES = 60;
|
||||
private static final int EVENT_MAXIMUM_ERRORS_IN_INTERVAL = 10;
|
||||
private static final int EVENT_ERROR_INTERVAL_SECONDS = 15;
|
||||
private static final int EVENT_STREAM_PAUSE = 3000;
|
||||
@ -111,18 +112,26 @@ public class TeslaVehicleHandler extends BaseThingHandler {
|
||||
protected boolean allowWakeUp;
|
||||
protected boolean allowWakeUpForCommands;
|
||||
protected boolean enableEvents = false;
|
||||
protected boolean useDriveState = false;
|
||||
protected boolean useAdvancedStates = false;
|
||||
protected boolean lastValidDriveStateNotNull = true;
|
||||
|
||||
protected long lastTimeStamp;
|
||||
protected long apiIntervalTimestamp;
|
||||
protected int apiIntervalErrors;
|
||||
protected long eventIntervalTimestamp;
|
||||
protected int eventIntervalErrors;
|
||||
protected int inactivity = MOVE_THRESHOLD_INTERVAL_MINUTES_DEFAULT;
|
||||
protected ReentrantLock lock;
|
||||
|
||||
protected double lastLongitude;
|
||||
protected double lastLatitude;
|
||||
protected long lastLocationChangeTimestamp;
|
||||
|
||||
protected long lastDriveStateChangeToNullTimestamp;
|
||||
protected long lastAdvModesTimestamp = System.currentTimeMillis();
|
||||
protected long lastStateTimestamp = System.currentTimeMillis();
|
||||
protected int backOffCounter = 0;
|
||||
|
||||
protected String lastState = "";
|
||||
protected boolean isInactive = false;
|
||||
|
||||
@ -150,6 +159,12 @@ public class TeslaVehicleHandler extends BaseThingHandler {
|
||||
allowWakeUp = (boolean) getConfig().get(TeslaBindingConstants.CONFIG_ALLOWWAKEUP);
|
||||
allowWakeUpForCommands = (boolean) getConfig().get(TeslaBindingConstants.CONFIG_ALLOWWAKEUPFORCOMMANDS);
|
||||
enableEvents = (boolean) getConfig().get(TeslaBindingConstants.CONFIG_ENABLEEVENTS);
|
||||
Number inactivityParam = (Number) getConfig().get(TeslaBindingConstants.CONFIG_INACTIVITY);
|
||||
inactivity = inactivityParam == null ? MOVE_THRESHOLD_INTERVAL_MINUTES_DEFAULT : inactivityParam.intValue();
|
||||
Boolean useDriveStateParam = (boolean) getConfig().get(TeslaBindingConstants.CONFIG_USEDRIVESTATE);
|
||||
useDriveState = useDriveStateParam == null ? false : useDriveStateParam;
|
||||
Boolean useAdvancedStatesParam = (boolean) getConfig().get(TeslaBindingConstants.CONFIG_USEDADVANCEDSTATES);
|
||||
useAdvancedStates = useAdvancedStatesParam == null ? false : useAdvancedStatesParam;
|
||||
|
||||
account = (TeslaAccountHandler) getBridge().getHandler();
|
||||
lock = new ReentrantLock();
|
||||
@ -535,17 +550,79 @@ public class TeslaVehicleHandler extends BaseThingHandler {
|
||||
protected boolean isInactive() {
|
||||
// vehicle is inactive in case
|
||||
// - it does not charge
|
||||
// - it has not moved in the observation period
|
||||
return isInactive && !isCharging() && !hasMovedInSleepInterval();
|
||||
// - it has not moved or optionally stopped reporting drive state, in the observation period
|
||||
// - it is not in dog, camp, keep, sentry or any other mode that keeps it online
|
||||
return isInactive && !isCharging() && !notReadyForSleep();
|
||||
}
|
||||
|
||||
protected boolean isCharging() {
|
||||
return chargeState != null && "Charging".equals(chargeState.charging_state);
|
||||
}
|
||||
|
||||
protected boolean hasMovedInSleepInterval() {
|
||||
return lastLocationChangeTimestamp > (System.currentTimeMillis()
|
||||
- (MOVE_THRESHOLD_INTERVAL_MINUTES * 60 * 1000));
|
||||
protected boolean notReadyForSleep() {
|
||||
boolean status;
|
||||
int computedInactivityPeriod = inactivity;
|
||||
|
||||
if (useAdvancedStates) {
|
||||
if (vehicleState.is_user_present && !isInMotion()) {
|
||||
logger.debug("Car is occupied but stationary.");
|
||||
if (lastAdvModesTimestamp < (System.currentTimeMillis()
|
||||
- (THRESHOLD_INTERVAL_FOR_ADVANCED_MINUTES * 60 * 1000))) {
|
||||
logger.debug("Ignoring after {} minutes.", THRESHOLD_INTERVAL_FOR_ADVANCED_MINUTES);
|
||||
} else {
|
||||
return (backOffCounter++ % 6 == 0); // using 6 should make sure 1 out of 5 pollers get serviced,
|
||||
// about every min.
|
||||
}
|
||||
} else if (vehicleState.sentry_mode) {
|
||||
logger.debug("Car is in sentry mode.");
|
||||
if (lastAdvModesTimestamp < (System.currentTimeMillis()
|
||||
- (THRESHOLD_INTERVAL_FOR_ADVANCED_MINUTES * 60 * 1000))) {
|
||||
logger.debug("Ignoring after {} minutes.", THRESHOLD_INTERVAL_FOR_ADVANCED_MINUTES);
|
||||
} else {
|
||||
return (backOffCounter++ % 6 == 0);
|
||||
}
|
||||
} else if ((vehicleState.center_display_state != 0) && (!isInMotion())) {
|
||||
logger.debug("Car is in camp, climate keep, dog, or other mode preventing sleep. Mode {}",
|
||||
vehicleState.center_display_state);
|
||||
return (backOffCounter++ % 6 == 0);
|
||||
} else {
|
||||
lastAdvModesTimestamp = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
|
||||
if (vehicleState.homelink_nearby) {
|
||||
computedInactivityPeriod = MOVE_THRESHOLD_INTERVAL_MINUTES_DEFAULT;
|
||||
logger.debug("Car is at home. Movement or drive state threshold is {} min.",
|
||||
MOVE_THRESHOLD_INTERVAL_MINUTES_DEFAULT);
|
||||
}
|
||||
|
||||
if (useDriveState) {
|
||||
if (driveState.shift_state != null) {
|
||||
logger.debug("Car drive state not null and not ready to sleep.");
|
||||
return true;
|
||||
} else {
|
||||
status = lastDriveStateChangeToNullTimestamp > (System.currentTimeMillis()
|
||||
- (computedInactivityPeriod * 60 * 1000));
|
||||
if (status) {
|
||||
logger.debug("Drivestate is null but has changed recently, therefore continuing to poll.");
|
||||
return status;
|
||||
} else {
|
||||
logger.debug("Drivestate has changed to null after interval {} min and can now be put to sleep.",
|
||||
computedInactivityPeriod);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
status = lastLocationChangeTimestamp > (System.currentTimeMillis()
|
||||
- (computedInactivityPeriod * 60 * 1000));
|
||||
if (status) {
|
||||
logger.debug("Car has moved recently and can not sleep");
|
||||
return status;
|
||||
} else {
|
||||
logger.debug("Car has not moved in {} min, and can sleep", computedInactivityPeriod);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean allowQuery() {
|
||||
@ -555,6 +632,7 @@ public class TeslaVehicleHandler extends BaseThingHandler {
|
||||
protected void setActive() {
|
||||
isInactive = false;
|
||||
lastLocationChangeTimestamp = System.currentTimeMillis();
|
||||
lastDriveStateChangeToNullTimestamp = System.currentTimeMillis();
|
||||
lastLatitude = 0;
|
||||
lastLongitude = 0;
|
||||
}
|
||||
@ -762,9 +840,6 @@ public class TeslaVehicleHandler extends BaseThingHandler {
|
||||
|
||||
protected void queryVehicleAndUpdate() {
|
||||
vehicle = queryVehicle();
|
||||
if (vehicle != null) {
|
||||
parseAndUpdate("queryVehicle", null, vehicleJSON);
|
||||
}
|
||||
}
|
||||
|
||||
public void parseAndUpdate(String request, String payLoad, String result) {
|
||||
@ -788,6 +863,16 @@ public class TeslaVehicleHandler extends BaseThingHandler {
|
||||
lastLongitude = driveState.longitude;
|
||||
lastLocationChangeTimestamp = System.currentTimeMillis();
|
||||
}
|
||||
logger.trace("Drive state: {}", driveState.shift_state);
|
||||
|
||||
if ((driveState.shift_state == null) && (lastValidDriveStateNotNull)) {
|
||||
logger.debug("Set NULL shiftstate time");
|
||||
lastValidDriveStateNotNull = false;
|
||||
lastDriveStateChangeToNullTimestamp = System.currentTimeMillis();
|
||||
} else if (driveState.shift_state != null) {
|
||||
logger.trace("Clear NULL shiftstate time");
|
||||
lastValidDriveStateNotNull = true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
@ -817,6 +902,18 @@ public class TeslaVehicleHandler extends BaseThingHandler {
|
||||
break;
|
||||
}
|
||||
case "queryVehicle": {
|
||||
if (vehicle != null) {
|
||||
logger.debug("Vehicle state is {}", vehicle.state);
|
||||
} else {
|
||||
logger.debug("Vehicle state is initializing or unknown");
|
||||
break;
|
||||
}
|
||||
|
||||
if (vehicle != null && "asleep".equals(vehicle.state)) {
|
||||
logger.debug("Vehicle is asleep.");
|
||||
break;
|
||||
}
|
||||
|
||||
if (vehicle != null && !lastState.equals(vehicle.state)) {
|
||||
lastState = vehicle.state;
|
||||
|
||||
@ -824,6 +921,7 @@ public class TeslaVehicleHandler extends BaseThingHandler {
|
||||
if (isAwake()) {
|
||||
logger.debug("Vehicle is now awake, updating all data");
|
||||
lastLocationChangeTimestamp = System.currentTimeMillis();
|
||||
lastDriveStateChangeToNullTimestamp = System.currentTimeMillis();
|
||||
requestAllData();
|
||||
}
|
||||
|
||||
@ -837,7 +935,7 @@ public class TeslaVehicleHandler extends BaseThingHandler {
|
||||
setActive();
|
||||
} else {
|
||||
boolean wasInactive = isInactive;
|
||||
isInactive = !isCharging() && !hasMovedInSleepInterval();
|
||||
isInactive = !isCharging() && !notReadyForSleep();
|
||||
|
||||
if (!wasInactive && isInactive) {
|
||||
lastStateTimestamp = System.currentTimeMillis();
|
||||
@ -967,7 +1065,6 @@ public class TeslaVehicleHandler extends BaseThingHandler {
|
||||
protected Runnable slowStateRunnable = () -> {
|
||||
try {
|
||||
queryVehicleAndUpdate();
|
||||
|
||||
boolean allowQuery = allowQuery();
|
||||
|
||||
if (allowQuery) {
|
||||
@ -980,7 +1077,9 @@ public class TeslaVehicleHandler extends BaseThingHandler {
|
||||
wakeUp();
|
||||
} else {
|
||||
if (isAwake()) {
|
||||
logger.debug("Vehicle is neither charging nor moving, skipping updates to allow it to sleep");
|
||||
logger.debug("slowpoll: Throttled to allow sleep, occupied/idle, or in a console mode");
|
||||
} else {
|
||||
lastAdvModesTimestamp = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1001,7 +1100,7 @@ public class TeslaVehicleHandler extends BaseThingHandler {
|
||||
wakeUp();
|
||||
} else {
|
||||
if (isAwake()) {
|
||||
logger.debug("Vehicle is neither charging nor moving, skipping updates to allow it to sleep");
|
||||
logger.debug("fastpoll: Throttled to allow sleep, occupied/idle, or in a console mode");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,12 +23,14 @@ public class VehicleState {
|
||||
public boolean dark_rims;
|
||||
public boolean has_spoiler;
|
||||
public boolean homelink_nearby;
|
||||
public boolean is_user_present;
|
||||
public boolean locked;
|
||||
public boolean notifications_supported;
|
||||
public boolean parsed_calendar_supported;
|
||||
public boolean remote_start;
|
||||
public boolean remote_start_supported;
|
||||
public boolean rhd;
|
||||
public boolean sentry_mode;
|
||||
public boolean valet_mode;
|
||||
public boolean valet_pin_needed;
|
||||
public float odometer;
|
||||
|
@ -132,6 +132,7 @@
|
||||
<parameter name="allowWakeup" type="boolean" required="false">
|
||||
<default>false</default>
|
||||
<label>Allow Wake-Up</label>
|
||||
<advanced>true</advanced>
|
||||
<description>Allows waking up the vehicle. Caution: This can result in huge vampire drain!</description>
|
||||
</parameter>
|
||||
<parameter name="allowWakeupForCommands" type="boolean" required="false">
|
||||
@ -143,8 +144,28 @@
|
||||
<parameter name="enableEvents" type="boolean" required="false">
|
||||
<default>false</default>
|
||||
<label>Enable Events</label>
|
||||
<advanced>true</advanced>
|
||||
<description>Enable the event stream for the vehicle</description>
|
||||
</parameter>
|
||||
<parameter name="inactivity" type="integer" min="5" required="false">
|
||||
<label>Inactivity Interval</label>
|
||||
<advanced>true</advanced>
|
||||
<description>The inactivity period in minutes, after which the binding stops for 20 minutes to let the car sleep.</description>
|
||||
<default>5</default>
|
||||
</parameter>
|
||||
<parameter name="useDriveState" type="boolean" required="false">
|
||||
<default>false</default>
|
||||
<label>Use Drive State for Inactivity</label>
|
||||
<advanced>true</advanced>
|
||||
<description>Use the drive state instead of location to determine vehicle inactivity.</description>
|
||||
</parameter>
|
||||
<parameter name="useAdvancedStatesForPolling" type="boolean" required="false">
|
||||
<default>false</default>
|
||||
<label>Use Console Modes and Occupancy for Inactivity</label>
|
||||
<advanced>true</advanced>
|
||||
<description>Use these states to help continue the fast polling of the API. Do not back off polling if in these
|
||||
states.</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
</thing-type>
|
||||
|
@ -139,6 +139,7 @@
|
||||
<parameter name="allowWakeup" type="boolean" required="false">
|
||||
<default>false</default>
|
||||
<label>Allow Wake-Up</label>
|
||||
<advanced>true</advanced>
|
||||
<description>Allows waking up the vehicle. Caution: This can result in huge vampire drain!</description>
|
||||
</parameter>
|
||||
<parameter name="allowWakeupForCommands" type="boolean" required="false">
|
||||
@ -150,8 +151,28 @@
|
||||
<parameter name="enableEvents" type="boolean" required="false">
|
||||
<default>false</default>
|
||||
<label>Enable Events</label>
|
||||
<advanced>true</advanced>
|
||||
<description>Enable the event stream for the vehicle</description>
|
||||
</parameter>
|
||||
<parameter name="inactivity" type="integer" min="5" required="false">
|
||||
<label>Inactivity Interval</label>
|
||||
<advanced>true</advanced>
|
||||
<description>The inactivity period in minutes, after which the binding stops for 20 minutes to let the car sleep.</description>
|
||||
<default>5</default>
|
||||
</parameter>
|
||||
<parameter name="useDriveState" type="boolean" required="false">
|
||||
<default>false</default>
|
||||
<label>Use Drive State for Inactivity</label>
|
||||
<advanced>true</advanced>
|
||||
<description>Use the drive state instead of location to determine vehicle inactivity.</description>
|
||||
</parameter>
|
||||
<parameter name="useAdvancedStatesForPolling" type="boolean" required="false">
|
||||
<default>false</default>
|
||||
<label>Use Console Modes and Occupancy for Inactivity</label>
|
||||
<advanced>true</advanced>
|
||||
<description>Use these states to help continue the fast polling of the API. Do not back off polling if in these
|
||||
states.</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
</thing-type>
|
||||
|
@ -139,6 +139,7 @@
|
||||
<parameter name="allowWakeup" type="boolean" required="false">
|
||||
<default>false</default>
|
||||
<label>Allow Wake-Up</label>
|
||||
<advanced>true</advanced>
|
||||
<description>Allows waking up the vehicle. Caution: This can result in huge vampire drain!</description>
|
||||
</parameter>
|
||||
<parameter name="allowWakeupForCommands" type="boolean" required="false">
|
||||
@ -150,8 +151,28 @@
|
||||
<parameter name="enableEvents" type="boolean" required="false">
|
||||
<default>false</default>
|
||||
<label>Enable Events</label>
|
||||
<advanced>true</advanced>
|
||||
<description>Enable the event stream for the vehicle</description>
|
||||
</parameter>
|
||||
<parameter name="inactivity" type="integer" min="5" required="false">
|
||||
<label>Inactivity Interval</label>
|
||||
<advanced>true</advanced>
|
||||
<description>The inactivity period in minutes, after which the binding stops for 20 minutes to let the car sleep.</description>
|
||||
<default>5</default>
|
||||
</parameter>
|
||||
<parameter name="useDriveState" type="boolean" required="false">
|
||||
<default>false</default>
|
||||
<label>Use Drive State for Inactivity</label>
|
||||
<advanced>true</advanced>
|
||||
<description>Use the drive state instead of location to determine vehicle inactivity.</description>
|
||||
</parameter>
|
||||
<parameter name="useAdvancedStatesForPolling" type="boolean" required="false">
|
||||
<default>false</default>
|
||||
<label>Use Console Modes and Occupancy for Inactivity</label>
|
||||
<advanced>true</advanced>
|
||||
<description>Use these states to help continue the fast polling of the API. Do not back off polling if in these
|
||||
states.</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
</thing-type>
|
||||
|
@ -134,6 +134,7 @@
|
||||
<parameter name="allowWakeup" type="boolean" required="false">
|
||||
<default>false</default>
|
||||
<label>Allow Wake-Up</label>
|
||||
<advanced>true</advanced>
|
||||
<description>Allows waking up the vehicle. Caution: This can result in huge vampire drain!</description>
|
||||
</parameter>
|
||||
<parameter name="allowWakeupForCommands" type="boolean" required="false">
|
||||
@ -145,8 +146,28 @@
|
||||
<parameter name="enableEvents" type="boolean" required="false">
|
||||
<default>false</default>
|
||||
<label>Enable Events</label>
|
||||
<advanced>true</advanced>
|
||||
<description>Enable the event stream for the vehicle</description>
|
||||
</parameter>
|
||||
<parameter name="inactivity" type="integer" min="5" required="false">
|
||||
<label>Inactivity Interval</label>
|
||||
<advanced>true</advanced>
|
||||
<description>The inactivity period in minutes, after which the binding stops for 20 minutes to let the car sleep.</description>
|
||||
<default>5</default>
|
||||
</parameter>
|
||||
<parameter name="useDriveState" type="boolean" required="false">
|
||||
<default>false</default>
|
||||
<label>Use Drive State for Inactivity</label>
|
||||
<advanced>true</advanced>
|
||||
<description>Use the drive state instead of location to determine vehicle inactivity.</description>
|
||||
</parameter>
|
||||
<parameter name="useAdvancedStatesForPolling" type="boolean" required="false">
|
||||
<default>false</default>
|
||||
<label>Use Console Modes and Occupancy for Inactivity</label>
|
||||
<advanced>true</advanced>
|
||||
<description>Use these states to help continue the fast polling of the API. Do not back off polling if in these
|
||||
states.</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
</thing-type>
|
||||
|
Loading…
Reference in New Issue
Block a user