mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-25 14:55:55 +01:00
[tesla] Adapt binding to changed API from Tesla backend (#14922)
* Adapt binding to changed API from Tesla backend Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
parent
fb16e90168
commit
f607dde3a5
@ -205,64 +205,64 @@ Bridge tesla:account:myaccount "My Tesla Account" [ refreshToken="xxxx" ] {
|
|||||||
demo.items:
|
demo.items:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
DateTime TeslaEventstamp {channel="model3:myaccount:mycar:eventstamp"}
|
DateTime TeslaEventstamp {channel="account:model3:myaccount:mycar:eventstamp"}
|
||||||
String TeslaState {channel="model3:myaccount:mycar:state"}
|
String TeslaState {channel="account:model3:myaccount:mycar:state"}
|
||||||
Number TeslaSpeed {channel="model3:myaccount:mycar:speed"}
|
Number TeslaSpeed {channel="account:model3:myaccount:mycar:speed"}
|
||||||
String TeslaShiftState {channel="model3:myaccount:mycar:shiftstate"}
|
String TeslaShiftState {channel="account:model3:myaccount:mycar:shiftstate"}
|
||||||
Number TeslaOdometer {channel="model3:myaccount:mycar:odometer"}
|
Number TeslaOdometer {channel="account:model3:myaccount:mycar:odometer"}
|
||||||
Number TeslaRange {channel="model3:myaccount:mycar:range"}
|
Number TeslaRange {channel="account:model3:myaccount:mycar:range"}
|
||||||
|
|
||||||
Number TeslaBatteryLevel {channel="model3:myaccount:mycar:batterylevel"}
|
Number TeslaBatteryLevel {channel="account:model3:myaccount:mycar:batterylevel"}
|
||||||
Number TeslaPower {channel="model3:myaccount:mycar:power"}
|
Number TeslaPower {channel="account:model3:myaccount:mycar:power"}
|
||||||
Number TeslaBatteryCurrent {channel="model3:myaccount:mycar:batterycurrent"}
|
Number TeslaBatteryCurrent {channel="account:model3:myaccount:mycar:batterycurrent"}
|
||||||
Number TeslaBatteryRange {channel="model3:myaccount:mycar:batteryrange"}
|
Number TeslaBatteryRange {channel="account:model3:myaccount:mycar:batteryrange"}
|
||||||
Number TeslaEstBatteryRange {channel="model3:myaccount:mycar:estimatedbatteryrange"}
|
Number TeslaEstBatteryRange {channel="account:model3:myaccount:mycar:estimatedbatteryrange"}
|
||||||
Number TeslaIdealBatteryRange {channel="model3:myaccount:mycar:idealbatteryrange"}
|
Number TeslaIdealBatteryRange {channel="account:model3:myaccount:mycar:idealbatteryrange"}
|
||||||
Number TeslaUsableBatteryLevel {channel="model3:myaccount:mycar:usablebatterylevel"}
|
Number TeslaUsableBatteryLevel {channel="account:model3:myaccount:mycar:usablebatterylevel"}
|
||||||
Switch TeslaPreconditioning {channel="model3:myaccount:mycar:preconditioning"}
|
Switch TeslaPreconditioning {channel="account:model3:myaccount:mycar:preconditioning"}
|
||||||
|
|
||||||
Switch TeslaCharge {channel="model3:myaccount:mycar:charge"}
|
Switch TeslaCharge {channel="account:model3:myaccount:mycar:charge"}
|
||||||
Switch TeslaChargeToMax {channel="model3:myaccount:mycar:chargetomax"}
|
Switch TeslaChargeToMax {channel="account:model3:myaccount:mycar:chargetomax"}
|
||||||
|
|
||||||
Dimmer TeslaChargeLimit {channel="model3:myaccount:mycar:chargelimit"}
|
Dimmer TeslaChargeLimit {channel="account:model3:myaccount:mycar:chargelimit"}
|
||||||
Number TeslaChargeRate {channel="model3:myaccount:mycar:chargerate"}
|
Number TeslaChargeRate {channel="account:model3:myaccount:mycar:chargerate"}
|
||||||
String TeslaChargingState {channel="model3:myaccount:mycar:chargingstate"}
|
String TeslaChargingState {channel="account:model3:myaccount:mycar:chargingstate"}
|
||||||
Number TeslaChargerPower {channel="model3:myaccount:mycar:chargerpower"}
|
Number TeslaChargerPower {channel="account:model3:myaccount:mycar:chargerpower"}
|
||||||
Number TeslaTimeToFullCharge {channel="model3:myaccount:mycar:timetofullcharge"}
|
Number TeslaTimeToFullCharge {channel="account:model3:myaccount:mycar:timetofullcharge"}
|
||||||
Number TeslaMaxCharges {channel="model3:myaccount:mycar:maxcharges"}
|
Number TeslaMaxCharges {channel="account:model3:myaccount:mycar:maxcharges"}
|
||||||
|
|
||||||
Number TeslaChargerVoltage {channel="model3:myaccount:mycar:chargervoltage"}
|
Number TeslaChargerVoltage {channel="account:model3:myaccount:mycar:chargervoltage"}
|
||||||
Number TeslaChargerPower {channel="model3:myaccount:mycar:chargerpower"}
|
Number TeslaChargerPower {channel="account:model3:myaccount:mycar:chargerpower"}
|
||||||
Number TeslaChargerCurrent {channel="model3:myaccount:mycar:chargercurrent"}
|
Number TeslaChargerCurrent {channel="account:model3:myaccount:mycar:chargercurrent"}
|
||||||
|
|
||||||
DateTime TeslaScheduledChargingStart {channel="model3:myaccount:mycar:scheduledchargingstart"}
|
DateTime TeslaScheduledChargingStart {channel="account:model3:myaccount:mycar:scheduledchargingstart"}
|
||||||
Dimmer TeslaSoC {channel="model3:myaccount:mycar:soc"}
|
Dimmer TeslaSoC {channel="account:model3:myaccount:mycar:soc"}
|
||||||
|
|
||||||
Switch TeslaDoorLock {channel="model3:myaccount:mycar:doorlock"}
|
Switch TeslaDoorLock {channel="account:model3:myaccount:mycar:doorlock"}
|
||||||
Switch TeslaHorn {channel="model3:myaccount:mycar:honkhorn"}
|
Switch TeslaHorn {channel="account:model3:myaccount:mycar:honkhorn"}
|
||||||
Switch TeslaStart {channel="model3:myaccount:mycar:remotestart"}
|
Switch TeslaStart {channel="account:model3:myaccount:mycar:remotestart"}
|
||||||
Switch TeslaSentry {channel="model3:myaccount:mycar:sentrymode"}
|
Switch TeslaSentry {channel="account:model3:myaccount:mycar:sentrymode"}
|
||||||
Switch TeslaLights {channel="model3:myaccount:mycar:flashlights"}
|
Switch TeslaLights {channel="account:model3:myaccount:mycar:flashlights"}
|
||||||
Switch TeslaValet {channel="model3:myaccount:mycar:valetmode"}
|
Switch TeslaValet {channel="account:model3:myaccount:mycar:valetmode"}
|
||||||
|
|
||||||
Switch TeslaWakeup {channel="model3:myaccount:mycar:wakeup"}
|
Switch TeslaWakeup {channel="account:model3:myaccount:mycar:wakeup"}
|
||||||
|
|
||||||
Switch TeslaBatteryHeater {channel="model3:myaccount:mycar:batteryheater"}
|
Switch TeslaBatteryHeater {channel="account:model3:myaccount:mycar:batteryheater"}
|
||||||
Switch TeslaFrontDefrost {channel="model3:myaccount:mycar:frontdefroster"}
|
Switch TeslaFrontDefrost {channel="account:model3:myaccount:mycar:frontdefroster"}
|
||||||
Switch TeslaRearDefrost {channel="model3:myaccount:mycar:reardefroster"}
|
Switch TeslaRearDefrost {channel="account:model3:myaccount:mycar:reardefroster"}
|
||||||
Switch TeslaLeftSeatHeater {channel="model3:myaccount:mycar:leftseatheater"}
|
Switch TeslaLeftSeatHeater {channel="account:model3:myaccount:mycar:leftseatheater"}
|
||||||
Switch TeslaRightSeatHeater {channel="model3:myaccount:mycar:rightseatheater"}
|
Switch TeslaRightSeatHeater {channel="account:model3:myaccount:mycar:rightseatheater"}
|
||||||
|
|
||||||
Switch TeslaHomelink {channel="model3:myaccount:mycar:homelink"}
|
Switch TeslaHomelink {channel="account:model3:myaccount:mycar:homelink"}
|
||||||
Location TeslaLocation {channel="model3:myaccount:mycar:location"}
|
Location TeslaLocation {channel="account:model3:myaccount:mycar:location"}
|
||||||
Number TeslaHeading {channel="model3:myaccount:mycar:heading"}
|
Number TeslaHeading {channel="account:model3:myaccount:mycar:heading"}
|
||||||
DateTime TeslaLocationTime {channel="model3:myaccount:mycar:gpstimestamp"}
|
DateTime TeslaLocationTime {channel="account:model3:myaccount:mycar:gpstimestamp"}
|
||||||
|
|
||||||
Switch TeslaAutoconditioning {channel="model3:myaccount:mycar:autoconditioning"}
|
Switch TeslaAutoconditioning {channel="account:model3:myaccount:mycar:autoconditioning"}
|
||||||
Number:Temperature TeslaTemperature {channel="model3:myaccount:mycar:temperature"}
|
Number:Temperature TeslaTemperature {channel="account:model3:myaccount:mycar:temperature"}
|
||||||
Number:Temperature TeslaTemperatureCombined {channel="model3:myaccount:mycar:combinedtemp"}
|
Number:Temperature TeslaTemperatureCombined {channel="account:model3:myaccount:mycar:combinedtemp"}
|
||||||
Number:Temperature TeslaInsideTemperature {channel="model3:myaccount:mycar:insidetemp"}
|
Number:Temperature TeslaInsideTemperature {channel="account:model3:myaccount:mycar:insidetemp"}
|
||||||
Number:Temperature TeslaOutsideTemperature {channel="model3:myaccount:mycar:outsidetemp"}
|
Number:Temperature TeslaOutsideTemperature {channel="account:model3:myaccount:mycar:outsidetemp"}
|
||||||
```
|
```
|
||||||
|
|
||||||
demo.sitemap:
|
demo.sitemap:
|
||||||
@ -337,23 +337,7 @@ sitemap main label="Main"
|
|||||||
}
|
}
|
||||||
Frame
|
Frame
|
||||||
{
|
{
|
||||||
Switch label="State" item=nTeslaState_chart icon=line mappings=[0="Hide", 1="Hour", 2="Day", 3="Week", 4="Month"]
|
Mapview item=TeslaLocation height=10
|
||||||
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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ public class TeslaBindingConstants {
|
|||||||
public static final String API_NAME = "Tesla Client API";
|
public static final String API_NAME = "Tesla Client API";
|
||||||
public static final String API_VERSION = "api/1/";
|
public static final String API_VERSION = "api/1/";
|
||||||
public static final String PATH_COMMAND = "command/{cmd}";
|
public static final String PATH_COMMAND = "command/{cmd}";
|
||||||
public static final String PATH_DATA_REQUEST = "data_request/{cmd}";
|
public static final String PATH_DATA_REQUEST = "vehicle_data";
|
||||||
public static final String PATH_VEHICLE_ID = "/{vid}/";
|
public static final String PATH_VEHICLE_ID = "/{vid}/";
|
||||||
public static final String PATH_WAKE_UP = "wake_up";
|
public static final String PATH_WAKE_UP = "wake_up";
|
||||||
public static final String PATH_ACCESS_TOKEN = "oauth/token";
|
public static final String PATH_ACCESS_TOKEN = "oauth/token";
|
||||||
@ -71,15 +71,6 @@ public class TeslaBindingConstants {
|
|||||||
public static final String COMMAND_WAKE_UP = "wake_up";
|
public static final String COMMAND_WAKE_UP = "wake_up";
|
||||||
public static final String DATA_THROTTLE = "datathrottle";
|
public static final String DATA_THROTTLE = "datathrottle";
|
||||||
|
|
||||||
// Tesla REST API vehicle states
|
|
||||||
public static final String CHARGE_STATE = "charge_state";
|
|
||||||
public static final String CLIMATE_STATE = "climate_state";
|
|
||||||
public static final String DRIVE_STATE = "drive_state";
|
|
||||||
public static final String GUI_STATE = "gui_settings";
|
|
||||||
public static final String MOBILE_ENABLED_STATE = "mobile_enabled";
|
|
||||||
public static final String VEHICLE_STATE = "vehicle_state";
|
|
||||||
public static final String VEHICLE_CONFIG = "vehicle_config";
|
|
||||||
|
|
||||||
public static final String BINDING_ID = "tesla";
|
public static final String BINDING_ID = "tesla";
|
||||||
|
|
||||||
// List of all Thing Type UIDs
|
// List of all Thing Type UIDs
|
||||||
|
@ -514,7 +514,7 @@ public class TeslaChannelSelectorProxy {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
MANAGED_CHARGING_START("managed_charging_start_time", "managedchargingstart", StringType.class, false),
|
MANAGED_CHARGING_START("managed_charging_start_time", "managedchargingstart", StringType.class, false),
|
||||||
MOBILE_ENABLED(TeslaBindingConstants.MOBILE_ENABLED_STATE, "mobileenabled", OnOffType.class, false) {
|
MOBILE_ENABLED("mobile_enabled", "mobileenabled", OnOffType.class, false) {
|
||||||
@Override
|
@Override
|
||||||
public State getState(String s, TeslaChannelSelectorProxy proxy, Map<String, String> properties) {
|
public State getState(String s, TeslaChannelSelectorProxy proxy, Map<String, String> properties) {
|
||||||
if ("true".equals(s)) {
|
if ("true".equals(s)) {
|
||||||
|
@ -36,6 +36,7 @@ import org.openhab.binding.tesla.internal.TeslaBindingConstants;
|
|||||||
import org.openhab.binding.tesla.internal.discovery.TeslaVehicleDiscoveryService;
|
import org.openhab.binding.tesla.internal.discovery.TeslaVehicleDiscoveryService;
|
||||||
import org.openhab.binding.tesla.internal.protocol.Vehicle;
|
import org.openhab.binding.tesla.internal.protocol.Vehicle;
|
||||||
import org.openhab.binding.tesla.internal.protocol.VehicleConfig;
|
import org.openhab.binding.tesla.internal.protocol.VehicleConfig;
|
||||||
|
import org.openhab.binding.tesla.internal.protocol.VehicleData;
|
||||||
import org.openhab.binding.tesla.internal.protocol.sso.TokenResponse;
|
import org.openhab.binding.tesla.internal.protocol.sso.TokenResponse;
|
||||||
import org.openhab.core.io.net.http.HttpClientFactory;
|
import org.openhab.core.io.net.http.HttpClientFactory;
|
||||||
import org.openhab.core.thing.Bridge;
|
import org.openhab.core.thing.Bridge;
|
||||||
@ -225,10 +226,10 @@ public class TeslaAccountHandler extends BaseBridgeHandler {
|
|||||||
Vehicle[] vehicleArray = gson.fromJson(jsonObject.getAsJsonArray("response"), Vehicle[].class);
|
Vehicle[] vehicleArray = gson.fromJson(jsonObject.getAsJsonArray("response"), Vehicle[].class);
|
||||||
|
|
||||||
for (Vehicle vehicle : vehicleArray) {
|
for (Vehicle vehicle : vehicleArray) {
|
||||||
String responseString = invokeAndParse(vehicle.id, VEHICLE_CONFIG, null, dataRequestTarget, 0);
|
String responseString = invokeAndParse(vehicle.id, null, null, dataRequestTarget, 0);
|
||||||
VehicleConfig vehicleConfig = null;
|
VehicleConfig vehicleConfig = null;
|
||||||
if (responseString != null && !responseString.isBlank()) {
|
if (responseString != null && !responseString.isBlank()) {
|
||||||
vehicleConfig = gson.fromJson(responseString, VehicleConfig.class);
|
vehicleConfig = gson.fromJson(responseString, VehicleData.class).vehicle_config;
|
||||||
}
|
}
|
||||||
for (VehicleListener listener : vehicleListeners) {
|
for (VehicleListener listener : vehicleListeners) {
|
||||||
listener.vehicleFound(vehicle, vehicleConfig);
|
listener.vehicleFound(vehicle, vehicleConfig);
|
||||||
|
@ -23,6 +23,7 @@ import java.text.SimpleDateFormat;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ScheduledFuture;
|
import java.util.concurrent.ScheduledFuture;
|
||||||
@ -48,6 +49,7 @@ import org.openhab.binding.tesla.internal.protocol.DriveState;
|
|||||||
import org.openhab.binding.tesla.internal.protocol.Event;
|
import org.openhab.binding.tesla.internal.protocol.Event;
|
||||||
import org.openhab.binding.tesla.internal.protocol.GUIState;
|
import org.openhab.binding.tesla.internal.protocol.GUIState;
|
||||||
import org.openhab.binding.tesla.internal.protocol.Vehicle;
|
import org.openhab.binding.tesla.internal.protocol.Vehicle;
|
||||||
|
import org.openhab.binding.tesla.internal.protocol.VehicleData;
|
||||||
import org.openhab.binding.tesla.internal.protocol.VehicleState;
|
import org.openhab.binding.tesla.internal.protocol.VehicleState;
|
||||||
import org.openhab.binding.tesla.internal.throttler.QueueChannelThrottler;
|
import org.openhab.binding.tesla.internal.throttler.QueueChannelThrottler;
|
||||||
import org.openhab.binding.tesla.internal.throttler.Rate;
|
import org.openhab.binding.tesla.internal.throttler.Rate;
|
||||||
@ -140,8 +142,7 @@ public class TeslaVehicleHandler extends BaseThingHandler {
|
|||||||
protected QueueChannelThrottler stateThrottler;
|
protected QueueChannelThrottler stateThrottler;
|
||||||
protected TeslaChannelSelectorProxy teslaChannelSelectorProxy = new TeslaChannelSelectorProxy();
|
protected TeslaChannelSelectorProxy teslaChannelSelectorProxy = new TeslaChannelSelectorProxy();
|
||||||
protected Thread eventThread;
|
protected Thread eventThread;
|
||||||
protected ScheduledFuture<?> fastStateJob;
|
protected ScheduledFuture<?> stateJob;
|
||||||
protected ScheduledFuture<?> slowStateJob;
|
|
||||||
protected WebSocketFactory webSocketFactory;
|
protected WebSocketFactory webSocketFactory;
|
||||||
|
|
||||||
private final Gson gson = new Gson();
|
private final Gson gson = new Gson();
|
||||||
@ -181,13 +182,8 @@ public class TeslaVehicleHandler extends BaseThingHandler {
|
|||||||
stateThrottler = new QueueChannelThrottler(firstRate, scheduler, channels);
|
stateThrottler = new QueueChannelThrottler(firstRate, scheduler, channels);
|
||||||
stateThrottler.addRate(secondRate);
|
stateThrottler.addRate(secondRate);
|
||||||
|
|
||||||
if (fastStateJob == null || fastStateJob.isCancelled()) {
|
if (stateJob == null || stateJob.isCancelled()) {
|
||||||
fastStateJob = scheduler.scheduleWithFixedDelay(fastStateRunnable, 0, FAST_STATUS_REFRESH_INTERVAL,
|
stateJob = scheduler.scheduleWithFixedDelay(stateRunnable, 0, SLOW_STATUS_REFRESH_INTERVAL,
|
||||||
TimeUnit.MILLISECONDS);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (slowStateJob == null || slowStateJob.isCancelled()) {
|
|
||||||
slowStateJob = scheduler.scheduleWithFixedDelay(slowStateRunnable, 0, SLOW_STATUS_REFRESH_INTERVAL,
|
|
||||||
TimeUnit.MILLISECONDS);
|
TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,14 +203,9 @@ public class TeslaVehicleHandler extends BaseThingHandler {
|
|||||||
logger.trace("Disposing the Tesla handler for {}", getThing().getUID());
|
logger.trace("Disposing the Tesla handler for {}", getThing().getUID());
|
||||||
lock.lock();
|
lock.lock();
|
||||||
try {
|
try {
|
||||||
if (fastStateJob != null && !fastStateJob.isCancelled()) {
|
if (stateJob != null && !stateJob.isCancelled()) {
|
||||||
fastStateJob.cancel(true);
|
stateJob.cancel(true);
|
||||||
fastStateJob = null;
|
stateJob = null;
|
||||||
}
|
|
||||||
|
|
||||||
if (slowStateJob != null && !slowStateJob.isCancelled()) {
|
|
||||||
slowStateJob.cancel(true);
|
|
||||||
slowStateJob = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (eventThread != null && !eventThread.isInterrupted()) {
|
if (eventThread != null && !eventThread.isInterrupted()) {
|
||||||
@ -494,7 +485,8 @@ public class TeslaVehicleHandler extends BaseThingHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void requestData(String command, String payLoad) {
|
public void requestData(String command, String payLoad) {
|
||||||
if (COMMAND_WAKE_UP.equals(command) || isAwake() || allowWakeUpForCommands) {
|
if (COMMAND_WAKE_UP.equals(command) || isAwake()
|
||||||
|
|| (!"vehicleData".equals(command) && allowWakeUpForCommands)) {
|
||||||
Request request = account.newRequest(this, command, payLoad, account.dataRequestTarget, false);
|
Request request = account.newRequest(this, command, payLoad, account.dataRequestTarget, false);
|
||||||
if (stateThrottler != null) {
|
if (stateThrottler != null) {
|
||||||
stateThrottler.submit(DATA_THROTTLE, request);
|
stateThrottler.submit(DATA_THROTTLE, request);
|
||||||
@ -527,11 +519,7 @@ public class TeslaVehicleHandler extends BaseThingHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void requestAllData() {
|
public void requestAllData() {
|
||||||
requestData(DRIVE_STATE);
|
requestData("vehicleData", null);
|
||||||
requestData(VEHICLE_STATE);
|
|
||||||
requestData(CHARGE_STATE);
|
|
||||||
requestData(CLIMATE_STATE);
|
|
||||||
requestData(GUI_STATE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean isAwake() {
|
protected boolean isAwake() {
|
||||||
@ -591,7 +579,7 @@ public class TeslaVehicleHandler extends BaseThingHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vehicleState.homelink_nearby) {
|
if (vehicleState != null && vehicleState.homelink_nearby) {
|
||||||
computedInactivityPeriod = MOVE_THRESHOLD_INTERVAL_MINUTES_DEFAULT;
|
computedInactivityPeriod = MOVE_THRESHOLD_INTERVAL_MINUTES_DEFAULT;
|
||||||
logger.debug("Car is at home. Movement or drive state threshold is {} min.",
|
logger.debug("Car is at home. Movement or drive state threshold is {} min.",
|
||||||
MOVE_THRESHOLD_INTERVAL_MINUTES_DEFAULT);
|
MOVE_THRESHOLD_INTERVAL_MINUTES_DEFAULT);
|
||||||
@ -671,21 +659,18 @@ public class TeslaVehicleHandler extends BaseThingHandler {
|
|||||||
JsonObject payloadObject = new JsonObject();
|
JsonObject payloadObject = new JsonObject();
|
||||||
payloadObject.addProperty("percent", percent);
|
payloadObject.addProperty("percent", percent);
|
||||||
sendCommand(COMMAND_SET_CHARGE_LIMIT, gson.toJson(payloadObject), account.commandTarget);
|
sendCommand(COMMAND_SET_CHARGE_LIMIT, gson.toJson(payloadObject), account.commandTarget);
|
||||||
requestData(CHARGE_STATE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setChargingAmps(int amps) {
|
public void setChargingAmps(int amps) {
|
||||||
JsonObject payloadObject = new JsonObject();
|
JsonObject payloadObject = new JsonObject();
|
||||||
payloadObject.addProperty("charging_amps", amps);
|
payloadObject.addProperty("charging_amps", amps);
|
||||||
sendCommand(COMMAND_SET_CHARGING_AMPS, gson.toJson(payloadObject), account.commandTarget);
|
sendCommand(COMMAND_SET_CHARGING_AMPS, gson.toJson(payloadObject), account.commandTarget);
|
||||||
requestData(CHARGE_STATE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSentryMode(boolean b) {
|
public void setSentryMode(boolean b) {
|
||||||
JsonObject payloadObject = new JsonObject();
|
JsonObject payloadObject = new JsonObject();
|
||||||
payloadObject.addProperty("on", b);
|
payloadObject.addProperty("on", b);
|
||||||
sendCommand(COMMAND_SET_SENTRY_MODE, gson.toJson(payloadObject), account.commandTarget);
|
sendCommand(COMMAND_SET_SENTRY_MODE, gson.toJson(payloadObject), account.commandTarget);
|
||||||
requestData(VEHICLE_STATE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSunroof(String state) {
|
public void setSunroof(String state) {
|
||||||
@ -693,7 +678,6 @@ public class TeslaVehicleHandler extends BaseThingHandler {
|
|||||||
JsonObject payloadObject = new JsonObject();
|
JsonObject payloadObject = new JsonObject();
|
||||||
payloadObject.addProperty("state", state);
|
payloadObject.addProperty("state", state);
|
||||||
sendCommand(COMMAND_SUN_ROOF, gson.toJson(payloadObject), account.commandTarget);
|
sendCommand(COMMAND_SUN_ROOF, gson.toJson(payloadObject), account.commandTarget);
|
||||||
requestData(VEHICLE_STATE);
|
|
||||||
} else {
|
} else {
|
||||||
logger.warn("Ignoring invalid command '{}' for sunroof.", state);
|
logger.warn("Ignoring invalid command '{}' for sunroof.", state);
|
||||||
}
|
}
|
||||||
@ -714,7 +698,6 @@ public class TeslaVehicleHandler extends BaseThingHandler {
|
|||||||
payloadObject.addProperty("driver_temp", driverTemperature);
|
payloadObject.addProperty("driver_temp", driverTemperature);
|
||||||
payloadObject.addProperty("passenger_temp", passenegerTemperature);
|
payloadObject.addProperty("passenger_temp", passenegerTemperature);
|
||||||
sendCommand(COMMAND_SET_TEMP, gson.toJson(payloadObject), account.commandTarget);
|
sendCommand(COMMAND_SET_TEMP, gson.toJson(payloadObject), account.commandTarget);
|
||||||
requestData(CLIMATE_STATE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCombinedTemperature(float temperature) {
|
public void setCombinedTemperature(float temperature) {
|
||||||
@ -733,14 +716,12 @@ public class TeslaVehicleHandler extends BaseThingHandler {
|
|||||||
JsonObject payloadObject = new JsonObject();
|
JsonObject payloadObject = new JsonObject();
|
||||||
payloadObject.addProperty("which_trunk", "front");
|
payloadObject.addProperty("which_trunk", "front");
|
||||||
sendCommand(COMMAND_ACTUATE_TRUNK, gson.toJson(payloadObject), account.commandTarget);
|
sendCommand(COMMAND_ACTUATE_TRUNK, gson.toJson(payloadObject), account.commandTarget);
|
||||||
requestData(VEHICLE_STATE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void openTrunk() {
|
public void openTrunk() {
|
||||||
JsonObject payloadObject = new JsonObject();
|
JsonObject payloadObject = new JsonObject();
|
||||||
payloadObject.addProperty("which_trunk", "rear");
|
payloadObject.addProperty("which_trunk", "rear");
|
||||||
sendCommand(COMMAND_ACTUATE_TRUNK, gson.toJson(payloadObject), account.commandTarget);
|
sendCommand(COMMAND_ACTUATE_TRUNK, gson.toJson(payloadObject), account.commandTarget);
|
||||||
requestData(VEHICLE_STATE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void closeTrunk() {
|
public void closeTrunk() {
|
||||||
@ -754,22 +735,18 @@ public class TeslaVehicleHandler extends BaseThingHandler {
|
|||||||
payloadObject.addProperty("password", String.format("%04d", pin));
|
payloadObject.addProperty("password", String.format("%04d", pin));
|
||||||
}
|
}
|
||||||
sendCommand(COMMAND_SET_VALET_MODE, gson.toJson(payloadObject), account.commandTarget);
|
sendCommand(COMMAND_SET_VALET_MODE, gson.toJson(payloadObject), account.commandTarget);
|
||||||
requestData(VEHICLE_STATE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void resetValetPin() {
|
public void resetValetPin() {
|
||||||
sendCommand(COMMAND_RESET_VALET_PIN, account.commandTarget);
|
sendCommand(COMMAND_RESET_VALET_PIN, account.commandTarget);
|
||||||
requestData(VEHICLE_STATE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMaxRangeCharging(boolean b) {
|
public void setMaxRangeCharging(boolean b) {
|
||||||
sendCommand(b ? COMMAND_CHARGE_MAX : COMMAND_CHARGE_STD, account.commandTarget);
|
sendCommand(b ? COMMAND_CHARGE_MAX : COMMAND_CHARGE_STD, account.commandTarget);
|
||||||
requestData(CHARGE_STATE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void charge(boolean b) {
|
public void charge(boolean b) {
|
||||||
sendCommand(b ? COMMAND_CHARGE_START : COMMAND_CHARGE_STOP, account.commandTarget);
|
sendCommand(b ? COMMAND_CHARGE_START : COMMAND_CHARGE_STOP, account.commandTarget);
|
||||||
requestData(CHARGE_STATE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void flashLights() {
|
public void flashLights() {
|
||||||
@ -782,17 +759,14 @@ public class TeslaVehicleHandler extends BaseThingHandler {
|
|||||||
|
|
||||||
public void openChargePort() {
|
public void openChargePort() {
|
||||||
sendCommand(COMMAND_OPEN_CHARGE_PORT, account.commandTarget);
|
sendCommand(COMMAND_OPEN_CHARGE_PORT, account.commandTarget);
|
||||||
requestData(CHARGE_STATE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void lockDoors(boolean b) {
|
public void lockDoors(boolean b) {
|
||||||
sendCommand(b ? COMMAND_DOOR_LOCK : COMMAND_DOOR_UNLOCK, account.commandTarget);
|
sendCommand(b ? COMMAND_DOOR_LOCK : COMMAND_DOOR_UNLOCK, account.commandTarget);
|
||||||
requestData(VEHICLE_STATE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void autoConditioning(boolean b) {
|
public void autoConditioning(boolean b) {
|
||||||
sendCommand(b ? COMMAND_AUTO_COND_START : COMMAND_AUTO_COND_STOP, account.commandTarget);
|
sendCommand(b ? COMMAND_AUTO_COND_START : COMMAND_AUTO_COND_STOP, account.commandTarget);
|
||||||
requestData(CLIMATE_STATE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void wakeUp() {
|
public void wakeUp() {
|
||||||
@ -854,194 +828,138 @@ public class TeslaVehicleHandler extends BaseThingHandler {
|
|||||||
public void parseAndUpdate(String request, String payLoad, String result) {
|
public void parseAndUpdate(String request, String payLoad, String result) {
|
||||||
final double locationThreshold = .0000001;
|
final double locationThreshold = .0000001;
|
||||||
|
|
||||||
JsonObject jsonObject = null;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (request != null && result != null && !"null".equals(result)) {
|
if (request != null && result != null && !"null".equals(result)) {
|
||||||
updateStatus(ThingStatus.ONLINE);
|
updateStatus(ThingStatus.ONLINE);
|
||||||
// first, update state objects
|
// first, update state objects
|
||||||
switch (request) {
|
if ("queryVehicle".equals(request)) {
|
||||||
case DRIVE_STATE: {
|
if (vehicle != null) {
|
||||||
driveState = gson.fromJson(result, DriveState.class);
|
logger.debug("Vehicle state is {}", vehicle.state);
|
||||||
|
updateState(TeslaChannelSelector.STATE.getChannelID(), new StringType(vehicle.state));
|
||||||
|
} else {
|
||||||
|
logger.debug("Vehicle state is initializing or unknown");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (Math.abs(lastLatitude - driveState.latitude) > locationThreshold
|
if (vehicle != null && "asleep".equals(vehicle.state)) {
|
||||||
|| Math.abs(lastLongitude - driveState.longitude) > locationThreshold) {
|
logger.debug("Vehicle is asleep.");
|
||||||
logger.debug("Vehicle moved, resetting last location timestamp");
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
lastLatitude = driveState.latitude;
|
if (vehicle != null && !lastState.equals(vehicle.state)) {
|
||||||
lastLongitude = driveState.longitude;
|
lastState = vehicle.state;
|
||||||
|
|
||||||
|
// in case vehicle changed to awake, refresh all data
|
||||||
|
if (isAwake()) {
|
||||||
|
logger.debug("Vehicle is now awake, updating all data");
|
||||||
lastLocationChangeTimestamp = System.currentTimeMillis();
|
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();
|
lastDriveStateChangeToNullTimestamp = System.currentTimeMillis();
|
||||||
} else if (driveState.shift_state != null) {
|
requestAllData();
|
||||||
logger.trace("Clear NULL shiftstate time");
|
|
||||||
lastValidDriveStateNotNull = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
setActive();
|
||||||
}
|
}
|
||||||
case GUI_STATE: {
|
|
||||||
guiState = gson.fromJson(result, GUIState.class);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case VEHICLE_STATE: {
|
|
||||||
vehicleState = gson.fromJson(result, VehicleState.class);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CHARGE_STATE: {
|
|
||||||
chargeState = gson.fromJson(result, ChargeState.class);
|
|
||||||
if (isCharging()) {
|
|
||||||
updateState(CHANNEL_CHARGE, OnOffType.ON);
|
|
||||||
} else {
|
|
||||||
updateState(CHANNEL_CHARGE, OnOffType.OFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
// reset timestamp if elapsed and set inactive to false
|
||||||
}
|
if (isInactive && lastStateTimestamp + (API_SLEEP_INTERVAL_MINUTES * 60 * 1000) < System
|
||||||
case CLIMATE_STATE: {
|
.currentTimeMillis()) {
|
||||||
climateState = gson.fromJson(result, ClimateState.class);
|
logger.debug("Vehicle did not fall asleep within sleep period, checking again");
|
||||||
BigDecimal avgtemp = roundBigDecimal(new BigDecimal(
|
setActive();
|
||||||
(climateState.driver_temp_setting + climateState.passenger_temp_setting) / 2.0f));
|
} else {
|
||||||
updateState(CHANNEL_COMBINED_TEMP, new QuantityType<>(avgtemp, SIUnits.CELSIUS));
|
boolean wasInactive = isInactive;
|
||||||
break;
|
isInactive = !isCharging() && !notReadyForSleep();
|
||||||
}
|
|
||||||
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)) {
|
if (!wasInactive && isInactive) {
|
||||||
logger.debug("Vehicle is asleep.");
|
lastStateTimestamp = System.currentTimeMillis();
|
||||||
break;
|
logger.debug("Vehicle is inactive");
|
||||||
}
|
|
||||||
|
|
||||||
if (vehicle != null && !lastState.equals(vehicle.state)) {
|
|
||||||
lastState = vehicle.state;
|
|
||||||
|
|
||||||
// in case vehicle changed to awake, refresh all data
|
|
||||||
if (isAwake()) {
|
|
||||||
logger.debug("Vehicle is now awake, updating all data");
|
|
||||||
lastLocationChangeTimestamp = System.currentTimeMillis();
|
|
||||||
lastDriveStateChangeToNullTimestamp = System.currentTimeMillis();
|
|
||||||
requestAllData();
|
|
||||||
}
|
|
||||||
|
|
||||||
setActive();
|
|
||||||
}
|
|
||||||
|
|
||||||
// reset timestamp if elapsed and set inactive to false
|
|
||||||
if (isInactive && lastStateTimestamp + (API_SLEEP_INTERVAL_MINUTES * 60 * 1000) < System
|
|
||||||
.currentTimeMillis()) {
|
|
||||||
logger.debug("Vehicle did not fall asleep within sleep period, checking again");
|
|
||||||
setActive();
|
|
||||||
} else {
|
|
||||||
boolean wasInactive = isInactive;
|
|
||||||
isInactive = !isCharging() && !notReadyForSleep();
|
|
||||||
|
|
||||||
if (!wasInactive && isInactive) {
|
|
||||||
lastStateTimestamp = System.currentTimeMillis();
|
|
||||||
logger.debug("Vehicle is inactive");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// secondly, reformat the response string to a JSON compliant
|
|
||||||
// object for some specific non-JSON compatible requests
|
|
||||||
switch (request) {
|
|
||||||
case MOBILE_ENABLED_STATE: {
|
|
||||||
jsonObject = new JsonObject();
|
|
||||||
jsonObject.addProperty(MOBILE_ENABLED_STATE, result);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
jsonObject = JsonParser.parseString(result).getAsJsonObject();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// process the result
|
|
||||||
if (jsonObject != null && result != null && !"null".equals(result)) {
|
|
||||||
// deal with responses for "set" commands, which get confirmed
|
|
||||||
// positively, or negatively, in which case a reason for failure
|
|
||||||
// is provided
|
|
||||||
if (jsonObject.get("reason") != null && jsonObject.get("reason").getAsString() != null) {
|
|
||||||
boolean requestResult = jsonObject.get("result").getAsBoolean();
|
|
||||||
logger.debug("The request ({}) execution was {}, and reported '{}'", request,
|
|
||||||
requestResult ? "successful" : "not successful", jsonObject.get("reason").getAsString());
|
|
||||||
} else {
|
|
||||||
Set<Map.Entry<String, JsonElement>> entrySet = jsonObject.entrySet();
|
|
||||||
|
|
||||||
long resultTimeStamp = 0;
|
|
||||||
for (Map.Entry<String, JsonElement> entry : entrySet) {
|
|
||||||
if ("timestamp".equals(entry.getKey())) {
|
|
||||||
resultTimeStamp = Long.parseLong(entry.getValue().getAsString());
|
|
||||||
if (logger.isTraceEnabled()) {
|
|
||||||
Date date = new Date(resultTimeStamp);
|
|
||||||
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
|
|
||||||
logger.trace("The request result timestamp is {}", dateFormatter.format(date));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if ("vehicleData".equals(request)) {
|
||||||
|
VehicleData vehicleData = gson.fromJson(result, VehicleData.class);
|
||||||
|
if (vehicleData == null) {
|
||||||
|
logger.error("Not able to parse response '{}'", result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
driveState = vehicleData.drive_state;
|
||||||
|
if (Math.abs(lastLatitude - driveState.latitude) > locationThreshold
|
||||||
|
|| Math.abs(lastLongitude - driveState.longitude) > locationThreshold) {
|
||||||
|
logger.debug("Vehicle moved, resetting last location timestamp");
|
||||||
|
|
||||||
|
lastLatitude = driveState.latitude;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
guiState = vehicleData.gui_settings;
|
||||||
|
|
||||||
|
vehicleState = vehicleData.vehicle_state;
|
||||||
|
|
||||||
|
chargeState = vehicleData.charge_state;
|
||||||
|
if (isCharging()) {
|
||||||
|
updateState(CHANNEL_CHARGE, OnOffType.ON);
|
||||||
|
} else {
|
||||||
|
updateState(CHANNEL_CHARGE, OnOffType.OFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
climateState = vehicleData.climate_state;
|
||||||
|
BigDecimal avgtemp = roundBigDecimal(new BigDecimal(
|
||||||
|
(climateState.driver_temp_setting + climateState.passenger_temp_setting) / 2.0f));
|
||||||
|
updateState(CHANNEL_COMBINED_TEMP, new QuantityType<>(avgtemp, SIUnits.CELSIUS));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
lock.lock();
|
lock.lock();
|
||||||
|
|
||||||
boolean proceed = true;
|
Set<Map.Entry<String, JsonElement>> entrySet = new HashSet<>();
|
||||||
if (resultTimeStamp < lastTimeStamp && request == DRIVE_STATE) {
|
|
||||||
proceed = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (proceed) {
|
entrySet.addAll(gson.toJsonTree(driveState, DriveState.class).getAsJsonObject().entrySet());
|
||||||
for (Map.Entry<String, JsonElement> entry : entrySet) {
|
entrySet.addAll(gson.toJsonTree(guiState, GUIState.class).getAsJsonObject().entrySet());
|
||||||
try {
|
entrySet.addAll(gson.toJsonTree(vehicleState, VehicleState.class).getAsJsonObject().entrySet());
|
||||||
TeslaChannelSelector selector = TeslaChannelSelector
|
entrySet.addAll(gson.toJsonTree(chargeState, ChargeState.class).getAsJsonObject().entrySet());
|
||||||
.getValueSelectorFromRESTID(entry.getKey());
|
entrySet.addAll(gson.toJsonTree(climateState, ClimateState.class).getAsJsonObject().entrySet());
|
||||||
if (!selector.isProperty()) {
|
|
||||||
if (!entry.getValue().isJsonNull()) {
|
for (Map.Entry<String, JsonElement> entry : entrySet) {
|
||||||
updateState(selector.getChannelID(), teslaChannelSelectorProxy.getState(
|
try {
|
||||||
entry.getValue().getAsString(), selector, editProperties()));
|
TeslaChannelSelector selector = TeslaChannelSelector
|
||||||
if (logger.isTraceEnabled()) {
|
.getValueSelectorFromRESTID(entry.getKey());
|
||||||
logger.trace(
|
if (!selector.isProperty()) {
|
||||||
"The variable/value pair '{}':'{}' is successfully processed",
|
if (!entry.getValue().isJsonNull()) {
|
||||||
entry.getKey(), entry.getValue());
|
updateState(selector.getChannelID(), teslaChannelSelectorProxy
|
||||||
}
|
.getState(entry.getValue().getAsString(), selector, editProperties()));
|
||||||
} else {
|
|
||||||
updateState(selector.getChannelID(), UnDefType.UNDEF);
|
|
||||||
}
|
|
||||||
} else if (!entry.getValue().isJsonNull()) {
|
|
||||||
Map<String, String> properties = editProperties();
|
|
||||||
properties.put(selector.getChannelID(), entry.getValue().getAsString());
|
|
||||||
updateProperties(properties);
|
|
||||||
if (logger.isTraceEnabled()) {
|
if (logger.isTraceEnabled()) {
|
||||||
logger.trace(
|
logger.trace("The variable/value pair '{}':'{}' is successfully processed",
|
||||||
"The variable/value pair '{}':'{}' is successfully used to set property '{}'",
|
entry.getKey(), entry.getValue());
|
||||||
entry.getKey(), entry.getValue(), selector.getChannelID());
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
updateState(selector.getChannelID(), UnDefType.UNDEF);
|
||||||
|
}
|
||||||
|
} else if (!entry.getValue().isJsonNull()) {
|
||||||
|
Map<String, String> properties = editProperties();
|
||||||
|
properties.put(selector.getChannelID(), entry.getValue().getAsString());
|
||||||
|
updateProperties(properties);
|
||||||
|
if (logger.isTraceEnabled()) {
|
||||||
|
logger.trace(
|
||||||
|
"The variable/value pair '{}':'{}' is successfully used to set property '{}'",
|
||||||
|
entry.getKey(), entry.getValue(), selector.getChannelID());
|
||||||
}
|
}
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
logger.trace("The variable/value pair '{}':'{}' is not (yet) supported",
|
|
||||||
entry.getKey(), entry.getValue());
|
|
||||||
} catch (ClassCastException | IllegalStateException e) {
|
|
||||||
logger.trace("An exception occurred while converting the JSON data : '{}'",
|
|
||||||
e.getMessage(), e);
|
|
||||||
}
|
}
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
logger.trace("The variable/value pair '{}':'{}' is not (yet) supported", entry.getKey(),
|
||||||
|
entry.getValue());
|
||||||
|
} catch (ClassCastException | IllegalStateException e) {
|
||||||
|
logger.trace("An exception occurred while converting the JSON data : '{}'",
|
||||||
|
e.getMessage(), e);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
logger.warn("The result for request '{}' is discarded due to an out of sync timestamp",
|
|
||||||
request);
|
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
@ -1069,40 +987,22 @@ public class TeslaVehicleHandler extends BaseThingHandler {
|
|||||||
return value.setScale(1, RoundingMode.HALF_EVEN);
|
return value.setScale(1, RoundingMode.HALF_EVEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Runnable slowStateRunnable = () -> {
|
protected Runnable stateRunnable = () -> {
|
||||||
try {
|
try {
|
||||||
queryVehicleAndUpdate();
|
queryVehicleAndUpdate();
|
||||||
boolean allowQuery = allowQuery();
|
boolean allowQuery = allowQuery();
|
||||||
|
|
||||||
if (allowQuery) {
|
if (allowQuery) {
|
||||||
requestData(CHARGE_STATE);
|
requestAllData();
|
||||||
requestData(CLIMATE_STATE);
|
|
||||||
requestData(GUI_STATE);
|
|
||||||
queryVehicle(MOBILE_ENABLED_STATE);
|
|
||||||
} else if (allowWakeUp) {
|
} else if (allowWakeUp) {
|
||||||
wakeUp();
|
wakeUp();
|
||||||
} else if (isAwake()) {
|
} else if (isAwake()) {
|
||||||
logger.debug("slowpoll: Throttled to allow sleep, occupied/idle, or in a console mode");
|
logger.debug("Throttled state polling to allow sleep, occupied/idle, or in a console mode");
|
||||||
} else {
|
} else {
|
||||||
lastAdvModesTimestamp = System.currentTimeMillis();
|
lastAdvModesTimestamp = System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.warn("Exception occurred in slowStateRunnable", e);
|
logger.warn("Exception occurred in stateRunnable", e);
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
protected Runnable fastStateRunnable = () -> {
|
|
||||||
if (getThing().getStatus() == ThingStatus.ONLINE) {
|
|
||||||
boolean allowQuery = allowQuery();
|
|
||||||
|
|
||||||
if (allowQuery) {
|
|
||||||
requestData(DRIVE_STATE);
|
|
||||||
requestData(VEHICLE_STATE);
|
|
||||||
} else if (allowWakeUp) {
|
|
||||||
wakeUp();
|
|
||||||
} else if (isAwake()) {
|
|
||||||
logger.debug("fastpoll: Throttled to allow sleep, occupied/idle, or in a console mode");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -0,0 +1,46 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2023 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.tesla.internal.protocol;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link VehicleData} is a data structure to capture
|
||||||
|
* variables sent by the Tesla API about a vehicle.
|
||||||
|
*
|
||||||
|
* @author Kai Kreuzer - Initial contribution
|
||||||
|
*/
|
||||||
|
public class VehicleData {
|
||||||
|
|
||||||
|
public String color;
|
||||||
|
public String display_name;
|
||||||
|
public String id;
|
||||||
|
public String option_codes;
|
||||||
|
public String vehicle_id;
|
||||||
|
public String vin;
|
||||||
|
public String tokens[];
|
||||||
|
public String state;
|
||||||
|
public boolean remote_start_enabled;
|
||||||
|
public boolean calendar_enabled;
|
||||||
|
public boolean notifications_enabled;
|
||||||
|
public String backseat_token;
|
||||||
|
public String backseat_token_updated_at;
|
||||||
|
|
||||||
|
public ChargeState charge_state;
|
||||||
|
public ClimateState climate_state;
|
||||||
|
public DriveState drive_state;
|
||||||
|
public GUIState gui_settings;
|
||||||
|
public VehicleConfig vehicle_config;
|
||||||
|
public VehicleState vehicle_state;
|
||||||
|
|
||||||
|
VehicleData() {
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user