[tesla] Fix discovery of Tesla vehicles from account (#14070)

* Fix discovery of Tesla vehicles from account

Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
Kai Kreuzer 2022-12-31 10:22:39 +01:00 committed by GitHub
parent 139aeed3ec
commit 2d5402656e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 186 additions and 34 deletions

View File

@ -22,9 +22,11 @@ Access is established through a Tesla account as a bridge.
The account cannot be automatically discovered, but has to be created manually.
Once an account is configured, it is automatically queried for associated vehicles and an Inbox entry is created for each of them.
Once an account is configured, it is queried for associated vehicles and an Inbox entry is created for each of them.
Note: Vehicles that are asleep might not be discovered, so you might want to wake it up through the Tesla app first.
Note: Vehicles that are asleep are discovered and put into the Inbox, but their model cannot be determined.
As an effect, their channels are missing until the vehicle wakes up and can be fully queried.
A vehicle can be manually woken up by opening the Tesla app and checking the vehicle status in there.
## Bridge Configuration

View File

@ -84,6 +84,7 @@ public class TeslaBindingConstants {
// List of all Thing Type UIDs
public static final ThingTypeUID THING_TYPE_ACCOUNT = new ThingTypeUID(BINDING_ID, "account");
public static final ThingTypeUID THING_TYPE_VEHICLE = new ThingTypeUID(BINDING_ID, "vehicle");
public static final ThingTypeUID THING_TYPE_MODELS = new ThingTypeUID(BINDING_ID, "models");
public static final ThingTypeUID THING_TYPE_MODEL3 = new ThingTypeUID(BINDING_ID, "model3");
public static final ThingTypeUID THING_TYPE_MODELX = new ThingTypeUID(BINDING_ID, "modelx");

View File

@ -27,6 +27,7 @@ import org.openhab.core.io.net.http.HttpClientFactory;
import org.openhab.core.io.net.http.WebSocketFactory;
import org.openhab.core.thing.Bridge;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingTypeMigrationService;
import org.openhab.core.thing.ThingTypeUID;
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
import org.openhab.core.thing.binding.ThingHandler;
@ -50,21 +51,24 @@ public class TeslaHandlerFactory extends BaseThingHandlerFactory {
private static final int EVENT_STREAM_CONNECT_TIMEOUT = 3;
private static final int EVENT_STREAM_READ_TIMEOUT = 200;
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_ACCOUNT, THING_TYPE_MODELS,
THING_TYPE_MODEL3, THING_TYPE_MODELX, THING_TYPE_MODELY);
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_ACCOUNT, THING_TYPE_VEHICLE,
THING_TYPE_MODELS, THING_TYPE_MODEL3, THING_TYPE_MODELX, THING_TYPE_MODELY);
private final ClientBuilder clientBuilder;
private final HttpClientFactory httpClientFactory;
private final WebSocketFactory webSocketFactory;
private final ThingTypeMigrationService thingTypeMigrationService;
@Activate
public TeslaHandlerFactory(@Reference ClientBuilder clientBuilder, @Reference HttpClientFactory httpClientFactory,
final @Reference WebSocketFactory webSocketFactory) {
final @Reference WebSocketFactory webSocketFactory,
final @Reference ThingTypeMigrationService thingTypeMigrationService) {
this.clientBuilder = clientBuilder //
.connectTimeout(EVENT_STREAM_CONNECT_TIMEOUT, TimeUnit.SECONDS)
.readTimeout(EVENT_STREAM_READ_TIMEOUT, TimeUnit.SECONDS);
this.httpClientFactory = httpClientFactory;
this.webSocketFactory = webSocketFactory;
this.thingTypeMigrationService = thingTypeMigrationService;
}
@Override
@ -77,7 +81,8 @@ public class TeslaHandlerFactory extends BaseThingHandlerFactory {
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
if (thingTypeUID.equals(THING_TYPE_ACCOUNT)) {
return new TeslaAccountHandler((Bridge) thing, clientBuilder.build(), httpClientFactory);
return new TeslaAccountHandler((Bridge) thing, clientBuilder.build(), httpClientFactory,
thingTypeMigrationService);
} else {
return new TeslaVehicleHandler(thing, webSocketFactory);
}

View File

@ -81,8 +81,10 @@ public class TeslaVehicleDiscoveryService extends AbstractDiscoveryService
@Override
public void vehicleFound(Vehicle vehicle, VehicleConfig vehicleConfig) {
ThingTypeUID type = identifyModel(vehicleConfig);
ThingTypeUID type = vehicleConfig == null ? TeslaBindingConstants.THING_TYPE_VEHICLE
: vehicleConfig.identifyModel();
if (type != null) {
logger.debug("Found a {} vehicle", type.getId());
ThingUID thingUID = new ThingUID(type, handler.getThing().getUID(), vehicle.vin);
DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withLabel(vehicle.display_name)
.withBridge(handler.getThing().getUID()).withProperty(TeslaBindingConstants.VIN, vehicle.vin)
@ -90,22 +92,4 @@ public class TeslaVehicleDiscoveryService extends AbstractDiscoveryService
thingDiscovered(discoveryResult);
}
}
private ThingTypeUID identifyModel(VehicleConfig vehicleConfig) {
logger.debug("Found a {} vehicle", vehicleConfig.car_type);
switch (vehicleConfig.car_type) {
case "models":
case "models2":
return TeslaBindingConstants.THING_TYPE_MODELS;
case "modelx":
return TeslaBindingConstants.THING_TYPE_MODELX;
case "model3":
return TeslaBindingConstants.THING_TYPE_MODEL3;
case "modely":
return TeslaBindingConstants.THING_TYPE_MODELY;
default:
logger.debug("Found unknown vehicle type '{}' - ignoring it.", vehicleConfig.car_type);
return null;
}
}
}

View File

@ -32,6 +32,7 @@ import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.openhab.binding.tesla.internal.TeslaBindingConstants;
import org.openhab.binding.tesla.internal.discovery.TeslaVehicleDiscoveryService;
import org.openhab.binding.tesla.internal.protocol.Vehicle;
import org.openhab.binding.tesla.internal.protocol.VehicleConfig;
@ -43,6 +44,7 @@ import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingStatus;
import org.openhab.core.thing.ThingStatusDetail;
import org.openhab.core.thing.ThingStatusInfo;
import org.openhab.core.thing.ThingTypeMigrationService;
import org.openhab.core.thing.binding.BaseBridgeHandler;
import org.openhab.core.thing.binding.ThingHandlerService;
import org.openhab.core.types.Command;
@ -80,6 +82,7 @@ public class TeslaAccountHandler extends BaseBridgeHandler {
final WebTarget wakeUpTarget;
private final TeslaSSOHandler ssoHandler;
private final ThingTypeMigrationService thingTypeMigrationService;
// Threading and Job related variables
protected ScheduledFuture<?> connectJob;
@ -96,10 +99,12 @@ public class TeslaAccountHandler extends BaseBridgeHandler {
private TokenResponse logonToken;
private final Set<VehicleListener> vehicleListeners = new HashSet<>();
public TeslaAccountHandler(Bridge bridge, Client teslaClient, HttpClientFactory httpClientFactory) {
public TeslaAccountHandler(Bridge bridge, Client teslaClient, HttpClientFactory httpClientFactory,
ThingTypeMigrationService thingTypeMigrationService) {
super(bridge);
this.teslaTarget = teslaClient.target(URI_OWNERS);
this.ssoHandler = new TeslaSSOHandler(httpClientFactory.getCommonHttpClient());
this.thingTypeMigrationService = thingTypeMigrationService;
this.vehiclesTarget = teslaTarget.path(API_VERSION).path(VEHICLES);
this.vehicleTarget = vehiclesTarget.path(PATH_VEHICLE_ID);
@ -222,10 +227,10 @@ public class TeslaAccountHandler extends BaseBridgeHandler {
for (Vehicle vehicle : vehicleArray) {
String responseString = invokeAndParse(vehicle.id, VEHICLE_CONFIG, null, dataRequestTarget, 0);
if (responseString == null || responseString.isBlank()) {
continue;
VehicleConfig vehicleConfig = null;
if (responseString != null && !responseString.isBlank()) {
vehicleConfig = gson.fromJson(responseString, VehicleConfig.class);
}
VehicleConfig vehicleConfig = gson.fromJson(responseString, VehicleConfig.class);
for (VehicleListener listener : vehicleListeners) {
listener.vehicleFound(vehicle, vehicleConfig);
}
@ -233,6 +238,15 @@ public class TeslaAccountHandler extends BaseBridgeHandler {
if (vehicle.vin.equals(vehicleThing.getConfiguration().get(VIN))) {
TeslaVehicleHandler vehicleHandler = (TeslaVehicleHandler) vehicleThing.getHandler();
if (vehicleHandler != null) {
if (TeslaBindingConstants.THING_TYPE_VEHICLE.equals(vehicleThing.getThingTypeUID())
&& vehicleConfig != null) {
// Seems the type of this vehicle has not been identified before, so let's switch the
// thing type of it
thingTypeMigrationService.migrateThingType(vehicleThing, vehicleConfig.identifyModel(),
vehicleThing.getConfiguration());
break;
}
logger.debug("Querying the vehicle: VIN {}", vehicle.vin);
String vehicleJSON = gson.toJson(vehicle);
vehicleHandler.parseAndUpdate("queryVehicle", null, vehicleJSON);
@ -353,8 +367,9 @@ public class TeslaAccountHandler extends BaseBridgeHandler {
lock.lock();
ThingStatusInfo status = getThing().getStatusInfo();
if (status.getStatus() != ThingStatus.ONLINE
&& status.getStatusDetail() != ThingStatusDetail.CONFIGURATION_ERROR) {
if ((status.getStatus() != ThingStatus.ONLINE
&& status.getStatusDetail() != ThingStatusDetail.CONFIGURATION_ERROR)
|| hasUnidentifiedVehicles()) {
logger.debug("Setting up an authenticated connection to the Tesla back-end");
ThingStatusInfo authenticationResult = authenticate();
@ -415,6 +430,11 @@ public class TeslaAccountHandler extends BaseBridgeHandler {
}
};
private boolean hasUnidentifiedVehicles() {
return getThing().getThings().stream()
.anyMatch(vehicle -> TeslaBindingConstants.THING_TYPE_VEHICLE.equals(vehicle.getThingTypeUID()));
}
protected class Request implements Runnable {
private static final int NO_OF_RETRIES = 3;

View File

@ -12,6 +12,8 @@
*/
package org.openhab.binding.tesla.internal.handler;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.tesla.internal.protocol.Vehicle;
import org.openhab.binding.tesla.internal.protocol.VehicleConfig;
@ -21,12 +23,14 @@ import org.openhab.binding.tesla.internal.protocol.VehicleConfig;
*
* @author Kai Kreuzer - Initial contribution
*/
@NonNullByDefault
public interface VehicleListener {
/**
* This method is called by the {@link TeslaAccountHandler}, if a vehicle is identified.
*
* @param vehicle a vehicle that was found within an account.
* @param vehicleConfig vehicle configuration that was read from the vehicle or null, if not available.
*/
void vehicleFound(Vehicle vehicle, VehicleConfig vehicleConfig);
void vehicleFound(Vehicle vehicle, @Nullable VehicleConfig vehicleConfig);
}

View File

@ -12,6 +12,9 @@
*/
package org.openhab.binding.tesla.internal.protocol;
import org.openhab.binding.tesla.internal.TeslaBindingConstants;
import org.openhab.core.thing.ThingTypeUID;
/**
* The {@link VehicleConfig} is a data structure to capture
* vehicle configuration variables sent by the Tesla Vehicle
@ -41,4 +44,20 @@ public class VehicleConfig {
public String third_row_seats;
public String trim_badging;
public String wheel_type;
public ThingTypeUID identifyModel() {
switch (car_type) {
case "models":
case "models2":
return TeslaBindingConstants.THING_TYPE_MODELS;
case "modelx":
return TeslaBindingConstants.THING_TYPE_MODELX;
case "model3":
return TeslaBindingConstants.THING_TYPE_MODEL3;
case "modely":
return TeslaBindingConstants.THING_TYPE_MODELY;
default:
return TeslaBindingConstants.THING_TYPE_VEHICLE;
}
}
}

View File

@ -15,6 +15,8 @@ thing-type.tesla.modelx.label = Tesla Model X
thing-type.tesla.modelx.description = A Tesla Model X Vehicle
thing-type.tesla.modely.label = Tesla Model Y
thing-type.tesla.modely.description = A Tesla Model Y Vehicle
thing-type.tesla.vehicle.label = Tesla
thing-type.tesla.vehicle.description = A Tesla Vehicle
# thing types config
@ -24,6 +26,14 @@ 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.enableEvents.label = Enable Events
thing-type.config.tesla.model3.enableEvents.description = Enable the event stream for the vehicle
thing-type.config.tesla.model3.inactivity.label = Inactivity Interval
thing-type.config.tesla.model3.inactivity.description = The inactivity period in minutes, after which the binding stops for 20 minutes to let the car sleep.
thing-type.config.tesla.model3.useAdvancedStatesForPolling.label = Use Console Modes and Occupancy for Inactivity
thing-type.config.tesla.model3.useAdvancedStatesForPolling.description = Use these states to help continue the fast polling of the API. Do not back off polling if in these states.
thing-type.config.tesla.model3.useDriveState.label = Use Drive State for Inactivity
thing-type.config.tesla.model3.useDriveState.description = Use the drive state instead of location to determine vehicle inactivity.
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
@ -32,6 +42,14 @@ 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.enableEvents.label = Enable Events
thing-type.config.tesla.models.enableEvents.description = Enable the event stream for the vehicle
thing-type.config.tesla.models.inactivity.label = Inactivity Interval
thing-type.config.tesla.models.inactivity.description = The inactivity period in minutes, after which the binding stops for 20 minutes to let the car sleep.
thing-type.config.tesla.models.useAdvancedStatesForPolling.label = Use Console Modes and Occupancy for Inactivity
thing-type.config.tesla.models.useAdvancedStatesForPolling.description = Use these states to help continue the fast polling of the API. Do not back off polling if in these states.
thing-type.config.tesla.models.useDriveState.label = Use Drive State for Inactivity
thing-type.config.tesla.models.useDriveState.description = Use the drive state instead of location to determine vehicle inactivity.
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
@ -40,6 +58,14 @@ 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.enableEvents.label = Enable Events
thing-type.config.tesla.modelx.enableEvents.description = Enable the event stream for the vehicle
thing-type.config.tesla.modelx.inactivity.label = Inactivity Interval
thing-type.config.tesla.modelx.inactivity.description = The inactivity period in minutes, after which the binding stops for 20 minutes to let the car sleep.
thing-type.config.tesla.modelx.useAdvancedStatesForPolling.label = Use Console Modes and Occupancy for Inactivity
thing-type.config.tesla.modelx.useAdvancedStatesForPolling.description = Use these states to help continue the fast polling of the API. Do not back off polling if in these states.
thing-type.config.tesla.modelx.useDriveState.label = Use Drive State for Inactivity
thing-type.config.tesla.modelx.useDriveState.description = Use the drive state instead of location to determine vehicle inactivity.
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
@ -48,10 +74,34 @@ 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.enableEvents.label = Enable Events
thing-type.config.tesla.modely.enableEvents.description = Enable the event stream for the vehicle
thing-type.config.tesla.modely.inactivity.label = Inactivity Interval
thing-type.config.tesla.modely.inactivity.description = The inactivity period in minutes, after which the binding stops for 20 minutes to let the car sleep.
thing-type.config.tesla.modely.useAdvancedStatesForPolling.label = Use Console Modes and Occupancy for Inactivity
thing-type.config.tesla.modely.useAdvancedStatesForPolling.description = Use these states to help continue the fast polling of the API. Do not back off polling if in these states.
thing-type.config.tesla.modely.useDriveState.label = Use Drive State for Inactivity
thing-type.config.tesla.modely.useDriveState.description = Use the drive state instead of location to determine vehicle inactivity.
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
thing-type.config.tesla.modely.vin.description = VIN of the vehicle
thing-type.config.tesla.vehicle.allowWakeup.label = Allow Wake-Up
thing-type.config.tesla.vehicle.allowWakeup.description = Allows waking up the vehicle. Caution: This can result in huge vampire drain!
thing-type.config.tesla.vehicle.allowWakeupForCommands.label = Allow Wake-Up For Commands
thing-type.config.tesla.vehicle.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.vehicle.enableEvents.label = Enable Events
thing-type.config.tesla.vehicle.enableEvents.description = Enable the event stream for the vehicle
thing-type.config.tesla.vehicle.inactivity.label = Inactivity Interval
thing-type.config.tesla.vehicle.inactivity.description = The inactivity period in minutes, after which the binding stops for 20 minutes to let the car sleep.
thing-type.config.tesla.vehicle.useAdvancedStatesForPolling.label = Use Console Modes and Occupancy for Inactivity
thing-type.config.tesla.vehicle.useAdvancedStatesForPolling.description = Use these states to help continue the fast polling of the API. Do not back off polling if in these states.
thing-type.config.tesla.vehicle.useDriveState.label = Use Drive State for Inactivity
thing-type.config.tesla.vehicle.useDriveState.description = Use the drive state instead of location to determine vehicle inactivity.
thing-type.config.tesla.vehicle.valetpin.label = Valet PIN
thing-type.config.tesla.vehicle.valetpin.description = PIN to use when enabling Valet Mode
thing-type.config.tesla.vehicle.vin.label = Vehicle Identification Number
thing-type.config.tesla.vehicle.vin.description = VIN of the vehicle
# channel types
@ -206,7 +256,7 @@ channel-type.tesla.minavailabletemp.label = Minimum Temperature
channel-type.tesla.minavailabletemp.description = Indicates the minimal inside temperature of the vehicle
channel-type.tesla.mobileenabled.label = Mobile Enabled
channel-type.tesla.mobileenabled.description = Indicates whether the vehicle can be remotely controlled
channel-type.tesla.notenoughpower.label = Not Enought Power
channel-type.tesla.notenoughpower.label = Not Enough Power
channel-type.tesla.notenoughpower.description = Indicates if not enough power (ON) is available to heat the vehicle
channel-type.tesla.notificationsenabled.label = Notifications Enabled
channel-type.tesla.notificationsenabled.description = Not documented / To be defined

View File

@ -421,7 +421,7 @@
</channel-type>
<channel-type id="notenoughpower" advanced="true">
<item-type>Switch</item-type>
<label>Not Enought Power</label>
<label>Not Enough Power</label>
<description>Indicates if not enough power (ON) is available to heat the vehicle</description>
<state readOnly="true"></state>
</channel-type>

View File

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="tesla"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="vehicle">
<supported-bridge-type-refs>
<bridge-type-ref id="account"/>
</supported-bridge-type-refs>
<label>Tesla</label>
<description>A Tesla Vehicle</description>
<config-description>
<parameter name="vin" type="text" required="true">
<label>Vehicle Identification Number</label>
<description>VIN of the vehicle</description>
</parameter>
<parameter name="valetpin" type="integer" min="0" max="9999" required="false">
<context>password</context>
<label>Valet PIN</label>
<description>PIN to use when enabling Valet Mode</description>
</parameter>
<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">
<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>
<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>
</thing:thing-descriptions>