diff --git a/CODEOWNERS b/CODEOWNERS index d2c062713ece2..82fc3dfbe5b46 100755 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -371,6 +371,7 @@ /bundles/org.openhab.binding.tellstick/ @openhab/add-ons-maintainers /bundles/org.openhab.binding.tesla/ @kgoderis /bundles/org.openhab.binding.teslapowerwall/ @psmedley +/bundles/org.openhab.binding.teslascope/ @psmedley /bundles/org.openhab.binding.tibber/ @kjoglum /bundles/org.openhab.binding.tivo/ @mlobstein /bundles/org.openhab.binding.touchwand/ @roieg diff --git a/bom/openhab-addons/pom.xml b/bom/openhab-addons/pom.xml index a572a4b2a52ca..e95b1542ac8f5 100644 --- a/bom/openhab-addons/pom.xml +++ b/bom/openhab-addons/pom.xml @@ -1851,6 +1851,11 @@ org.openhab.binding.teslapowerwall ${project.version} + + org.openhab.addons.bundles + org.openhab.binding.teslascope + ${project.version} + org.openhab.addons.bundles org.openhab.binding.tibber diff --git a/bundles/org.openhab.binding.teslascope/NOTICE b/bundles/org.openhab.binding.teslascope/NOTICE new file mode 100644 index 0000000000000..38d625e349232 --- /dev/null +++ b/bundles/org.openhab.binding.teslascope/NOTICE @@ -0,0 +1,13 @@ +This content is produced and maintained by the openHAB project. + +* Project home: https://www.openhab.org + +== Declared Project Licenses + +This program and the accompanying materials are made available under the terms +of the Eclipse Public License 2.0 which is available at +https://www.eclipse.org/legal/epl-2.0/. + +== Source Code + +https://github.com/openhab/openhab-addons diff --git a/bundles/org.openhab.binding.teslascope/README.md b/bundles/org.openhab.binding.teslascope/README.md new file mode 100644 index 0000000000000..d532010d4e1cc --- /dev/null +++ b/bundles/org.openhab.binding.teslascope/README.md @@ -0,0 +1,242 @@ +# Teslascope Binding + +This binding integrates [Tesla Electrical Vehicles](https://www.tesla.com). +The integration happens through the [Teslascope](https://www.teslascope.com) API. + +## Supported Things + +All Tesla vehicles supported by Teslascope are supported. +Each vehicle is represented by its own `vehicle` Thing. + +## Discovery + +Auto-discovery is not currently supported. + +## Thing Configuration + +As a minimum, the apiKey and publicID are needed: +| Thing Parameter | Default Value | Required | Advanced | Description | +|-----------------|---------------|----------|----------|--------------------------------------------------------------------------------------| +| apiKey | N/A | Yes | No | apiKey provided by Teslascope | +| publicID | N/A | Yes | No | Vehicle Public ID listed in Teslascope | +| refreshInterval | 60 | No | Yes | The frequency with which to refresh information from Teslascope specified in seconds | + +## Channels + +All vehicles support a huge number of channels - the following list shows the standard ones: + +| Channel ID | Item Type | Label | Description | +|-------------------|----------------------|--------------------|---------------------------------------------------------------------------------------------| +| auto-conditioning | Switch | Auto Conditioning | Turns on auto-conditioning (a/c or heating) | +| battery-level | Number:Dimensionless | Battery Level | State of the battery in % | +| charging-state | String | Charging State | “Starting”, “Complete”, “Charging”, “Disconnected”, “Stopped”, “NoPower” | +| charge-port | Switch | Charge Port | Open the Charge Port (ON) or indicates the state of the Charge Port (ON/OFF if Open/Closed) | +| climate | Switch | Climate | Climate status indicator | +| door-lock | Switch | Door Lock | Lock or unlock the car | +| inside-temp | Number:Temperature | Inside Temperature | Indicates the inside temperature of the vehicle | +| location | Location | Location | The actual position of the vehicle | +| odometer | Number:Length | Odometer | Odometer of the vehicle | +| speed | Number:Speed | Speed | Vehicle speed | +| vin | String | VIN | Vehicle Identification Number | +| vehicle-name | String | Name | Vehicle Name | +| vehicle-state | String | Vehicle State | Vehicle State | + +Additionally, these advanced channels are available (not all are available on all vehicle types, e.g., the sunroof): + +| Channel ID | Item Type | Label | Description | +|-----------------------------|--------------------------|-------------------------------|----------------------------------------------------------------------------------------------------------| +| battery-range | Number:Length | Battery Range | Range of the battery | +| center-rear-seat-heater | Switch | Center Rear Seat Heater | Indicates if the center rear seat heater is switched on | +| charge | Switch | Charge | Start (ON) or stop (OFF) charging | +| charge-energy-added | Number:Energy | Charge Energy Added | Energy added, in kWh, during the last charging session | +| charge-limit-soc-standard | Dimmer | Charge Limit SOC Standard | Standard charging limit of the vehicle, in % | +| charge-rate | Number:Speed | Charge Rate | Distance per hour charging rate | +| charger-power | Number:Power | Charger Power | Power actually delivered by the charger | +| charger-voltage | Number:ElectricPotential | Charger Voltage | Voltage (V) actually presented by the charger | +| driver-front-door | Contact | Driver Front Door | Indicates if the front door at the driver's side is open | +| driver-rear-door | Contact | Driver Rear Door | Indicates if the rear door at the driver's side is open | +| driver-temp | Number:Temperature | Driver Temperature | Indicates the auto conditioning temperature set at the driver's side | +| estimated-battery-range | Number:Length | Estimated Battery Range | Estimated battery range | +| fan | Number | Fan | Indicates the speed (0-7) of the fan | +| flash-lights | Switch | Flash Lights | Flash the lights of the car (when ON is received) | +| front-defroster | Switch | Front Defroster | Indicates if the front defroster is enabled | +| front-trunk | Switch | Front Trunk | Indicates if the front trunk is opened, or open the front trunk when ON is received | +| heading | Number:Angle | Heading | Indicates the (compass) heading of the car, in 0-360 degrees | +| honk-horn | Switch | Honk the Horn | Honk the horn of the vehicle, when ON is received | +| homelink | Switch | Homelink Nearby | Indicates if the Home Link is nearby | +| left-temp-direction | Number | Left Temperature Direction | Not documented / To be defined | +| location | Location | Location | The actual position of the vehicle | +| left-seat-heater | Switch | Left Seat Heater | Indicates if the left seat heater is switched on | +| left-rear-seat-heater | Switch | Left Rear Seat Heater | Indicates if the left rear seat heater is switched on | +| left-rear-back-seat-heater | Number | Left Rear Backseat Heater | Indicates the level (0, 1, 2, or 3) of the left rear backseat heater | +| min-available-temp | Number:Temperature | Minimum Temperature | Indicates the minimal inside temperature of the vehicle | +| max-available-temp | Number:Temperature | Maximum Temperature | Indicates the maximum inside temperature of the vehicle | +| outside-temp | Number:Temperature | Outside Temperature | Indicates the outside temperature of the vehicle | +| passenger-temp | Number | Passenger Temperature | Indicates the auto conditioning temperature set at the passenger's side | +| passenger-front-door | Contact | Passenger Front Door | Indicates if the front door at the passenger's side is opened | +| passenger-rear-door | Contact | Passenger Rear Door | Indicates if the rear door at the passenger's side is opened | +| power | Number:Power | Power | Net kW flowing in (+) or out (-) of the battery | +| preconditioning | Switch | Preconditioning | Indicates if preconditioning is activated | +| rear-defroster | Switch | Rear Defroster | Indicates if the rear defroster is enabled | +| rear-trunk | Switch | Rear Trunk | Indicates if the rear trunk is opened, or open/close the rear trunk when ON/OFF is received | +| right-seat-heater | Switch | Right Seat Heater | Indicates if the right seat heater is switched on | +| right-rear-seat-heater | Switch | Right Rear Seat Heater | Indicates if the right rear seat heater is switched on | +| right-rear-back-seat-heater | Number | Right Rear Backseat Heater | Indicates the level (0, 1, 2, or 3) of the right rear backseat heater | +| right-temp-direction | Number | Right Temperature Direction | Not documented / To be defined | +| scheduled-charging-pending | Switch | Scheduled Charging Pending | Indicates if a scheduled charging session is still pending | +| scheduled-charging-start | DateTime | Scheduled Charging Start | Indicates when the scheduled charging session will start, in yyyy-MM-dd'T'HH:mm:ss format | +| sentry-mode | Switch | Sentry Mode | Activates or deactivates sentry mode | +| shift-state | String | Shift State | Indicates the state of the transmission, “P”, “D”, “R”, or “N” | +| side-mirror-heaters | Switch | Side Mirror Heaters | Indicates if the side mirror heaters are switched on | +| smart-preconditioning | Switch | Smart Preconditioning | Indicates if smart preconditioning is switched on | +| software-update-available | Switch | Update Available | Car software or map update available, automatically generated on non-empty "update status" | +| software-update-status | String | Update Status | Car software or map update status, e.g. "downloading_wifi_wait", "installing" | +| software-update-version | String | Update Version | Car software or map version to update to, e.g. "2023.32.9", "EU-2023.32-14783" for map updates, or empty | +| steering-wheel-heater | Switch | Steering Wheel Heater | Turns On/Off the steering wheel heater | +| sunroof-state | String | Sunroof State | Valid states are “unknown”, “open”, “closed”, “vent”, “comfort”. Accepts commands "close" and "vent". | +| sunroof | Dimmer | Sunroof | Indicates the opening state of the sunroof (0% closed, 100% fully open) | +| time-to-full-charge | Number | Time To Full Charge | Number of hours to fully charge the battery | +| tpms-pressure-fl | Number:Pressure | Tyre Pressure FL | Tyre Pressure Front Left in Bar | +| tpms-pressure-fr | Number:Pressure | Tyre Pressure FR | Tyre Pressure Front Right in Bar | +| tpms-pressure-rl | Number:Pressure | Tyre Pressure RL | Tyre Pressure Rear Left in Bar | +| tpms-pressure-rr | Number:Pressure | Tyre Pressure RR | Tyre Pressure Rear Right in Bar | +| tpms-soft-warning-fl | Switch | Tyre Pressure Soft Warning FL | Tyre Pressure Soft Warning Front Left | +| tpms-soft-warning-fr | Switch | Tyre Pressure Soft Warning FR | Tyre Pressure Soft Warning Front Right | +| tpms-soft-warning-rl | Switch | Tyre Pressure Soft Warning RL | Tyre Pressure Soft Warning Rear Left | +| tpms-soft-warning-rr | Switch | Tyre Pressure Soft Warning RR | Tyre Pressure Soft Warning Rear Right | +| usable-battery-level | Number | Usable Battery Level | Indicates the % of battery that can be used for vehicle functions like driving | +| valet-mode | Switch | Valet Mode | Enable or disable Valet Mode | +| wiper-blade-heater | Switch | Wiperblade Heater | Indicates if the wiperblade heater is switched on | + +## Full Example + +### `demo.things`: + +```java +teslascope:vehicle:model3 [ apiKey="xxxx", publicID="aXb3" ] +``` + +### `example.items`: + +```java +String TeslaVehicleName {channel="teslascope:vehicle:model3:vehicle-name"} +String TeslaVehicleState {channel="teslascope:vehicle:model3:vehicle-state"} +String TeslaVIN {channel="teslascope:vehicle:model3:vin"} +Number TeslaSpeed {channel="teslascope:vehicle:model3:speed"} +String TeslaShiftState {channel="teslascope:vehicle:model3:shift-state"} +Number TeslaOdometer {channel="teslascope:vehicle:model3:odometer"} +Number TeslaRange {channel="teslascope:vehicle:model3:range"} + +Number TeslaBatteryLevel {channel="teslascope:vehicle:model3:battery-level"} +Number TeslaPower {channel="teslascope:vehicle:model3:power"} +Number TeslaBatteryRange {channel="teslascope:vehicle:model3:battery-range"} +Number TeslaEstBatteryRange {channel="teslascope:vehicle:model3:estimated-battery-range"} +Switch TeslaPreconditioning {channel="teslascope:vehicle:model3:preconditioning"} + +Switch TeslaCharge {channel="teslascope:vehicle:model3:charge"} + +Dimmer TeslaChargeLimit {channel="teslascope:vehicle:model3:charge-limit"} +Number TeslaChargeRate {channel="teslascope:vehicle:model3:charge-rate"} +String TeslaChargingState {channel="teslascope:vehicle:model3:charging-state"} +Number TeslaChargerPower {channel="teslascope:vehicle:model3:charger-power"} +Number TeslaTimeToFullCharge {channel="teslascope:vehicle:model3:time-to-full-charge"} + +Number TeslaChargerVoltage {channel="teslascope:vehicle:model3:charger-voltage"} +Number TeslaChargerPower {channel="teslascope:vehicle:model3:charger-power"} + +DateTime TeslaScheduledChargingStart {channel="teslascope:vehicle:model3:scheduled-charging-start"} + +Switch TeslaDoorLock {channel="teslascope:vehicle:model3:door-lock"} +Switch TeslaHorn {channel="teslascope:vehicle:model3:honk-horn"} +Switch TeslaSentry {channel="teslascope:vehicle:model3:sentry-mode"} +Switch TeslaLights {channel="teslascope:vehicle:model3:flash-lights"} +Switch TeslaValet {channel="teslascope:vehicle:model3:valet-mode"} + +Switch TeslaFrontDefrost {channel="teslascope:vehicle:model3:front-defroster"} +Switch TeslaRearDefrost {channel="teslascope:vehicle:model3:rear-defroster"} +Switch TeslaLeftSeatHeater {channel="teslascope:vehicle:model3:left-seat-heater"} +Switch TeslaRightSeatHeater {channel="teslascope:vehicle:model3:right-seat-heater"} + +Switch TeslaHomelink {channel="teslascope:vehicle:model3:homelink"} +Location TeslaLocation {channel="teslascope:vehicle:model3:location"} +Number TeslaHeading {channel="teslascope:vehicle:model3:heading"} + +Switch TeslaAutoconditioning {channel="teslascope:vehicle:model3:auto-conditioning"} +Number:Temperature TeslaTemperature {channel="teslascope:vehicle:model3:temperature"} +Number:Temperature TeslaInsideTemperature {channel="teslascope:vehicle:model3:inside-temp"} +Number:Temperature TeslaOutsideTemperature {channel="teslascope:vehicle:model3:outside-temp"} + +Number:Pressure TeslaTPMSPressureFL {channel="teslascope:vehicle:model3:tpms-pressure-fl"} +Number:Pressure TeslaTPMSPressureFR {channel="teslascope:vehicle:model3:tpms-pressure-fr"} +Number:Pressure TeslaTPMSPressureRL {channel="teslascope:vehicle:model3:tpms-pressure-rl"} +Number:Pressure TeslaTPMSPressureRR {channel="teslascope:vehicle:model3:tpms-pressure-rr"} + +Switch TeslaTPMSSoftWarningFL {channel="teslascope:vehicle:model3:tpms-soft-warning-fl"} +Switch TeslaTPMSSoftWarningFR {channel="teslascope:vehicle:model3:tpms-soft-warning-fr"} +Switch TeslaTPMSSoftWarningRL {channel="teslascope:vehicle:model3:tpms-soft-warning-rl"} +Switch TeslaTPMSSoftWarningRR {channel="teslascope:vehicle:model3:tpms-soft-warning-rr"} +``` + +### `example.sitemap`: + +```perl +sitemap main label="Main" +{ + Text item=TeslaUsableBatteryLevel label="Car" icon="tesla" valuecolor=[<=20="red",>60="green"] + { + Frame + { + Text item=TeslaState label="State [%s]" icon="" + Text item=TeslaHomelink label="Homelink Available[%s]" icon="" + Text item=TeslaSpeed label="Speed [%.1f]" + Text item=TeslaShiftState label="Shift State [%s]" icon="" + Text item=TeslaShiftState + 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=TeslaPower + Text item=TeslaBatteryRange label="Battery Range [%.1f miles]" + Text item=TeslaEstBatteryRange label="Battery Est 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]" + } + Frame + { + Switch item=TeslaDoorLock label="Doorlock" + Switch item=TeslaHorn label="Horn" + Switch item=TeslaLights label="Lights" + Switch item=TeslaValet label="Valet Mode" + Switch item=TeslaSentry label="Sentry Mode" + + 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 + { + Mapview item=TeslaLocation height=10 + } + } +} +``` diff --git a/bundles/org.openhab.binding.teslascope/pom.xml b/bundles/org.openhab.binding.teslascope/pom.xml new file mode 100644 index 0000000000000..cccf5dbe7ae35 --- /dev/null +++ b/bundles/org.openhab.binding.teslascope/pom.xml @@ -0,0 +1,17 @@ + + + + 4.0.0 + + + org.openhab.addons.bundles + org.openhab.addons.reactor.bundles + 4.3.0-SNAPSHOT + + + org.openhab.binding.teslascope + + openHAB Add-ons :: Bundles :: Teslascope Binding + + diff --git a/bundles/org.openhab.binding.teslascope/src/main/feature/feature.xml b/bundles/org.openhab.binding.teslascope/src/main/feature/feature.xml new file mode 100644 index 0000000000000..a33f949564d68 --- /dev/null +++ b/bundles/org.openhab.binding.teslascope/src/main/feature/feature.xml @@ -0,0 +1,9 @@ + + + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.teslascope/${project.version} + + diff --git a/bundles/org.openhab.binding.teslascope/src/main/java/org/openhab/binding/teslascope/internal/TeslascopeAuthenticationException.java b/bundles/org.openhab.binding.teslascope/src/main/java/org/openhab/binding/teslascope/internal/TeslascopeAuthenticationException.java new file mode 100644 index 0000000000000..483be4cef4338 --- /dev/null +++ b/bundles/org.openhab.binding.teslascope/src/main/java/org/openhab/binding/teslascope/internal/TeslascopeAuthenticationException.java @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2010-2024 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.teslascope.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * Exception for when an unexpected response is received from the Teslascope API. + * + * @author Paul Smedley - Initial contribution + * + */ +@NonNullByDefault +public class TeslascopeAuthenticationException extends Exception { + private static final long serialVersionUID = 529232811860854017L; + + public TeslascopeAuthenticationException(String message) { + super(message); + } + + public TeslascopeAuthenticationException(Throwable ex) { + super(ex); + } + + public TeslascopeAuthenticationException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/bundles/org.openhab.binding.teslascope/src/main/java/org/openhab/binding/teslascope/internal/TeslascopeBindingConstants.java b/bundles/org.openhab.binding.teslascope/src/main/java/org/openhab/binding/teslascope/internal/TeslascopeBindingConstants.java new file mode 100644 index 0000000000000..c3ca8c171dfc6 --- /dev/null +++ b/bundles/org.openhab.binding.teslascope/src/main/java/org/openhab/binding/teslascope/internal/TeslascopeBindingConstants.java @@ -0,0 +1,105 @@ +/** + * Copyright (c) 2010-2024 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.teslascope.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.core.thing.ThingTypeUID; + +/** + * The {@link TeslascopeBindingConstants} class defines common constants, which are + * used across the whole binding. + * + * @author Paul Smedley - Initial contribution + */ +@NonNullByDefault +public class TeslascopeBindingConstants { + + private static final String BINDING_ID = "teslascope"; + + // List of all Thing Type UIDs + public static final ThingTypeUID TESLASCOPE_THING = new ThingTypeUID(BINDING_ID, "vehicle"); + + // List of all Channel ids + public static final String CHANNEL_VIN = "vin"; + public static final String CHANNEL_VEHICLE_NAME = "vehicle-name"; + public static final String CHANNEL_VEHICLE_STATE = "vehicle-state"; + public static final String CHANNEL_ODOMETER = "odometer"; + public static final String CHANNEL_BATTERY_LEVEL = "battery-level"; + public static final String CHANNEL_CHARGING_STATE = "charging-state"; + public static final String CHANNEL_TPMS_FL = "tpms-pressure-fl"; + public static final String CHANNEL_TPMS_FR = "tpms-pressure-fr"; + public static final String CHANNEL_TPMS_RL = "tpms-pressure-rl"; + public static final String CHANNEL_TPMS_RR = "tpms-pressure-rr"; + public static final String CHANNEL_TPMS_SOFT_WARNING_FL = "tpms-soft-warning-fl"; + public static final String CHANNEL_TPMS_SOFT_WARNING_FR = "tpms-soft-warning-fr"; + public static final String CHANNEL_TPMS_SOFT_WARNING_RL = "tpms-soft-warning-rl"; + public static final String CHANNEL_TPMS_SOFT_WARNING_RR = "tpms-soft-warning-rr"; + public static final String CHANNEL_SOFTWARE_UPDATE_AVAILABLE = "software-update-available"; + public static final String CHANNEL_SOFTWARE_UPDATE_STATUS = "software-update-status"; + public static final String CHANNEL_SOFTWARE_UPDATE_VERSION = "software-update-version"; + public static final String CHANNEL_AUTOCONDITIONING = "auto-conditioning"; + public static final String CHANNEL_BATTERY_RANGE = "battery-range"; + public static final String CHANNEL_CENTER_REAR_SEAT_HEATER = "center-rear-seat-heater"; + public static final String CHANNEL_CHARGE = "charge"; + public static final String CHANNEL_CHARGE_ENERGY_ADDED = "charge-energy-added"; + public static final String CHANNEL_CHARGE_LIMIT_SOC_STANDARD = "charge-limit-soc-standard"; + public static final String CHANNEL_CHARGE_PORT = "charge-port"; + public static final String CHANNEL_CHARGE_RATE = "charge-rate"; + public static final String CHANNEL_CHARGER_POWER = "charger-power"; + public static final String CHANNEL_CHARGER_VOLTAGE = "charger-voltage"; + public static final String CHANNEL_CLIMATE = "climate"; + public static final String CHANNEL_DOOR_LOCK = "door-lock"; + public static final String CHANNEL_DRIVER_FRONT_DOOR = "driver-front-door"; + public static final String CHANNEL_DRIVER_REAR_DOOR = "driver-rear-door"; + public static final String CHANNEL_DRIVER_TEMP = "driver-temp"; + public static final String CHANNEL_ESTIMATED_BATTERY_RANGE = "estimated-battery-range"; + public static final String CHANNEL_FAN = "fan"; + public static final String CHANNEL_FLASH_LIGHTS = "flash-lights"; + public static final String CHANNEL_FRONT_DEFROSTER = "front-defroster"; + public static final String CHANNEL_FRONT_TRUNK = "front-trunk"; + public static final String CHANNEL_HEADING = "heading"; + public static final String CHANNEL_HOMELINK = "homelink"; + public static final String CHANNEL_HONK_HORN = "honk-horn"; + public static final String CHANNEL_INSIDE_TEMP = "inside-temp"; + public static final String CHANNEL_LEFT_REAR_SEAT_HEATER = "left-rear-seat-heater"; + public static final String CHANNEL_LEFT_SEAT_HEATER = "left-seat-heater"; + public static final String CHANNEL_LEFT_TEMP_DIRECTION = "left-temp-direction"; + public static final String CHANNEL_LOCATION = "location"; + public static final String CHANNEL_MIN_AVAILABLE_TEMP = "min-available-temp"; + public static final String CHANNEL_MAX_AVAILABLE_TEMP = "max-available-temp"; + public static final String CHANNEL_OUTSIDE_TEMP = "outside-temp"; + public static final String CHANNEL_PASSENGER_FRONT_DOOR = "passenger-front-door"; + public static final String CHANNEL_PASSENGER_REAR_DOOR = "passenger-rear-door"; + public static final String CHANNEL_PASSENGER_TEMP = "passenger-temp"; + public static final String CHANNEL_POWER = "power"; + public static final String CHANNEL_PRECONDITIONING = "preconditioning"; + public static final String CHANNEL_REAR_DEFROSTER = "rear-defroster"; + public static final String CHANNEL_REAR_TRUNK = "rear-trunk"; + public static final String CHANNEL_RIGHT_REAR_SEAT_HEATER = "right-rear-seat-heater"; + public static final String CHANNEL_RIGHT_SEAT_HEATER = "right-seat-heater"; + public static final String CHANNEL_RIGHT_TEMP_DIRECTION = "right-temp-direction"; + public static final String CHANNEL_SCHEDULED_CHARGING_PENDING = "scheduled-charging-pending"; + public static final String CHANNEL_SCHEDULED_CHARGING_START = "scheduled-charging-start"; + public static final String CHANNEL_SENTRY_MODE = "sentry-mode"; + public static final String CHANNEL_SHIFT_STATE = "shift-state"; + public static final String CHANNEL_SIDE_MIRROR_HEATERS = "side-mirror-heaters"; + public static final String CHANNEL_SMARTPRECONDITIONG = "smart-preconditioning"; + public static final String CHANNEL_SPEED = "speed"; + public static final String CHANNEL_STEERING_WHEEL_HEATER = "steering-wheel-heater"; + public static final String CHANNEL_SUNROOF = "sunroof"; + public static final String CHANNEL_SUNROOF_STATE = "sunroof-state"; + public static final String CHANNEL_TIME_TO_FULL_CHARGE = "time-to-full-charge"; + public static final String CHANNEL_USABLE_BATTERY_LEVEL = "usable-battery-level"; + public static final String CHANNEL_VALET_MODE = "valet-mode"; + public static final String CHANNEL_WIPER_BLADE_HEATER = "wiper-blade-heater"; +} diff --git a/bundles/org.openhab.binding.teslascope/src/main/java/org/openhab/binding/teslascope/internal/TeslascopeCommunicationException.java b/bundles/org.openhab.binding.teslascope/src/main/java/org/openhab/binding/teslascope/internal/TeslascopeCommunicationException.java new file mode 100644 index 0000000000000..ea95e21cf17f5 --- /dev/null +++ b/bundles/org.openhab.binding.teslascope/src/main/java/org/openhab/binding/teslascope/internal/TeslascopeCommunicationException.java @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2010-2024 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.teslascope.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * Exception for when an unexpected response is received from the Teslascope API. + * + * @author Paul Smedley - Initial contribution + * + */ +@NonNullByDefault +public class TeslascopeCommunicationException extends Exception { + private static final long serialVersionUID = 529232811860854017L; + + public TeslascopeCommunicationException(String message) { + super(message); + } + + public TeslascopeCommunicationException(Throwable ex) { + super(ex); + } + + public TeslascopeCommunicationException(@Nullable String message, Throwable cause) { + super(message, cause); + } +} diff --git a/bundles/org.openhab.binding.teslascope/src/main/java/org/openhab/binding/teslascope/internal/TeslascopeConfiguration.java b/bundles/org.openhab.binding.teslascope/src/main/java/org/openhab/binding/teslascope/internal/TeslascopeConfiguration.java new file mode 100644 index 0000000000000..d948cfc467121 --- /dev/null +++ b/bundles/org.openhab.binding.teslascope/src/main/java/org/openhab/binding/teslascope/internal/TeslascopeConfiguration.java @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2010-2024 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.teslascope.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link TeslascopeConfiguration} class contains fields mapping thing configuration parameters. + * + * @author Paul Smedley - Initial contribution + */ +@NonNullByDefault +public class TeslascopeConfiguration { + + public String apiKey = ""; + public String publicID = ""; + public int refreshInterval = 60; +} diff --git a/bundles/org.openhab.binding.teslascope/src/main/java/org/openhab/binding/teslascope/internal/TeslascopeHandler.java b/bundles/org.openhab.binding.teslascope/src/main/java/org/openhab/binding/teslascope/internal/TeslascopeHandler.java new file mode 100644 index 0000000000000..cc57dcfc470a9 --- /dev/null +++ b/bundles/org.openhab.binding.teslascope/src/main/java/org/openhab/binding/teslascope/internal/TeslascopeHandler.java @@ -0,0 +1,376 @@ +/** + * Copyright (c) 2010-2024 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.teslascope.internal; + +import static org.openhab.binding.teslascope.internal.TeslascopeBindingConstants.*; + +import java.util.concurrent.Future; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jetty.client.HttpClient; +import org.openhab.binding.teslascope.internal.api.DetailedInformation; +import org.openhab.core.library.types.DecimalType; +import org.openhab.core.library.types.OnOffType; +import org.openhab.core.library.types.OpenClosedType; +import org.openhab.core.library.types.PointType; +import org.openhab.core.library.types.QuantityType; +import org.openhab.core.library.types.StringType; +import org.openhab.core.library.unit.ImperialUnits; +import org.openhab.core.library.unit.MetricPrefix; +import org.openhab.core.library.unit.SIUnits; +import org.openhab.core.library.unit.Units; +import org.openhab.core.thing.ChannelUID; +import org.openhab.core.thing.Thing; +import org.openhab.core.thing.ThingStatus; +import org.openhab.core.thing.ThingStatusDetail; +import org.openhab.core.thing.binding.BaseThingHandler; +import org.openhab.core.types.Command; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.Gson; + +/** + * The {@link TeslascopeHandler} is responsible for handling commands, which are + * sent to one of the channels. + * + * @author Paul Smedley - Initial contribution + */ +@NonNullByDefault +public class TeslascopeHandler extends BaseThingHandler { + + private final Logger logger = LoggerFactory.getLogger(TeslascopeHandler.class); + + private TeslascopeConfiguration config = new TeslascopeConfiguration(); + private TeslascopeWebTargets webTargets; + private @Nullable ScheduledFuture pollFuture; + + private final Gson gson = new Gson(); + + public TeslascopeHandler(Thing thing, HttpClient httpClient) { + super(thing); + webTargets = new TeslascopeWebTargets(httpClient); + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + try { + switch (channelUID.getId()) { + case TeslascopeBindingConstants.CHANNEL_AUTOCONDITIONING: + if (command instanceof OnOffType onOffCommand) { + setAutoConditioning(onOffCommand == OnOffType.ON); + } + break; + case TeslascopeBindingConstants.CHANNEL_CHARGE: + if (command instanceof OnOffType onOffCommand) { + charge(onOffCommand == OnOffType.ON); + } + break; + case TeslascopeBindingConstants.CHANNEL_CHARGE_PORT: + if (command instanceof OnOffType onOffCommand) { + chargeDoor(onOffCommand == OnOffType.ON); + } + break; + case TeslascopeBindingConstants.CHANNEL_DOOR_LOCK: + if (command instanceof OnOffType onOffCommand) { + lock(onOffCommand == OnOffType.ON); + } + break; + case TeslascopeBindingConstants.CHANNEL_FLASH_LIGHTS: + if (command instanceof OnOffType onOffCommand) { + flashLights(); + return; + } + break; + case TeslascopeBindingConstants.CHANNEL_FRONT_TRUNK: + if (command instanceof OnOffType onOffCommand) { + openFrunk(); + return; + } + break; + case TeslascopeBindingConstants.CHANNEL_HONK_HORN: + if (command instanceof OnOffType onOffCommand) { + honkHorn(); + return; + } + break; + case TeslascopeBindingConstants.CHANNEL_REAR_TRUNK: + if (command instanceof OnOffType onOffCommand) { + openTrunk(); + return; + } + break; + case TeslascopeBindingConstants.CHANNEL_SENTRY_MODE: + if (command instanceof OnOffType onOffCommand) { + sentry(onOffCommand == OnOffType.ON); + } + break; + default: + logger.debug("Received command ({}) of wrong type for thing '{}' on channel {}", command, + thing.getUID().getAsString(), channelUID.getId()); + } + } catch (TeslascopeAuthenticationException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); + } catch (TeslascopeCommunicationException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); + } + } + + @Override + public void initialize() { + config = getConfigAs(TeslascopeConfiguration.class); + if (config.apiKey.isBlank()) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "@text/offline.conf-error.no-api-key"); + return; + } + + updateStatus(ThingStatus.UNKNOWN); + + schedulePoll(); + } + + @Override + public void dispose() { + super.dispose(); + stopPoll(); + } + + private void schedulePoll() { + logger.debug("Scheduling poll every {} s", config.refreshInterval); + this.pollFuture = scheduler.scheduleWithFixedDelay(this::pollStatus, 0, config.refreshInterval, + TimeUnit.SECONDS); + } + + private void stopPoll() { + final Future future = pollFuture; + if (future != null) { + future.cancel(true); + pollFuture = null; + } + } + + private void pollStatus() { + String response = ""; + + try { + response = webTargets.getDetailedInformation(config.publicID, config.apiKey); + updateStatus(ThingStatus.ONLINE); + } catch (TeslascopeAuthenticationException e) { + logger.debug("Unexpected authentication error connecting to Teslascope API", e); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); + return; + } catch (TeslascopeCommunicationException e) { + logger.debug("Unexpected error connecting to Teslascope API", e); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); + return; + } + + DetailedInformation detailedInformation = gson.fromJson(response, DetailedInformation.class); + + if (detailedInformation != null) { + updateState(TeslascopeBindingConstants.CHANNEL_VIN, new StringType(detailedInformation.vin)); + updateState(TeslascopeBindingConstants.CHANNEL_VEHICLE_NAME, new StringType(detailedInformation.name)); + updateState(TeslascopeBindingConstants.CHANNEL_VEHICLE_STATE, new StringType(detailedInformation.state)); + updateState(TeslascopeBindingConstants.CHANNEL_ODOMETER, + new QuantityType<>(detailedInformation.odometer, ImperialUnits.MILE)); + + // charge state + updateState(TeslascopeBindingConstants.CHANNEL_BATTERY_LEVEL, + new DecimalType(detailedInformation.chargeState.batteryLevel)); + updateState(TeslascopeBindingConstants.CHANNEL_USABLE_BATTERY_LEVEL, + new DecimalType(detailedInformation.chargeState.usableBatteryLevel)); + updateState(TeslascopeBindingConstants.CHANNEL_BATTERY_RANGE, + new QuantityType<>(detailedInformation.chargeState.batteryRange, ImperialUnits.MILE)); + updateState(TeslascopeBindingConstants.CHANNEL_ESTIMATED_BATTERY_RANGE, + new QuantityType<>(detailedInformation.chargeState.estBatteryRange, ImperialUnits.MILE)); + // charge_enable_request isn't the right flag to determine if car is charging or not + updateState(TeslascopeBindingConstants.CHANNEL_CHARGE, + OnOffType.from("Charging".equals(detailedInformation.chargeState.chargingState))); + updateState(TeslascopeBindingConstants.CHANNEL_CHARGE_ENERGY_ADDED, + new QuantityType<>(detailedInformation.chargeState.chargeEnergyAdded, Units.KILOWATT_HOUR)); + updateState(CHANNEL_CHARGE_LIMIT_SOC_STANDARD, + new DecimalType(detailedInformation.chargeState.chargeLimitSoc / 100)); + updateState(TeslascopeBindingConstants.CHANNEL_CHARGE_PORT, + OnOffType.from(1 == detailedInformation.chargeState.chargePortDoorOpen)); + updateState(TeslascopeBindingConstants.CHANNEL_CHARGE_RATE, + new QuantityType<>(detailedInformation.chargeState.chargeRate, ImperialUnits.MILES_PER_HOUR)); + updateState(TeslascopeBindingConstants.CHANNEL_CHARGER_POWER, + new QuantityType<>(detailedInformation.chargeState.chargerPower, MetricPrefix.KILO(Units.WATT))); + updateState(TeslascopeBindingConstants.CHANNEL_CHARGER_VOLTAGE, + new QuantityType<>(detailedInformation.chargeState.chargerVoltage, Units.VOLT)); + updateState(TeslascopeBindingConstants.CHANNEL_TIME_TO_FULL_CHARGE, + new QuantityType<>(detailedInformation.chargeState.timeToFullCharge, Units.HOUR)); + updateState(TeslascopeBindingConstants.CHANNEL_CHARGING_STATE, + new StringType(detailedInformation.chargeState.chargingState)); + updateState(TeslascopeBindingConstants.CHANNEL_SCHEDULED_CHARGING_PENDING, + OnOffType.from(1 == detailedInformation.chargeState.scheduledChargingPending)); + updateState(TeslascopeBindingConstants.CHANNEL_SCHEDULED_CHARGING_START, + new StringType(detailedInformation.chargeState.scheduledChargingStartTime)); + + // climate state + updateState(TeslascopeBindingConstants.CHANNEL_AUTOCONDITIONING, + OnOffType.from(1 == detailedInformation.climateState.isAutoConditioningOn)); + updateState(TeslascopeBindingConstants.CHANNEL_CLIMATE, + OnOffType.from(1 == detailedInformation.climateState.isClimateOn)); + updateState(TeslascopeBindingConstants.CHANNEL_FRONT_DEFROSTER, + OnOffType.from(1 == detailedInformation.climateState.isFrontDefrosterOn)); + updateState(TeslascopeBindingConstants.CHANNEL_PRECONDITIONING, + OnOffType.from(1 == detailedInformation.climateState.isPreconditioning)); + updateState(TeslascopeBindingConstants.CHANNEL_REAR_DEFROSTER, + OnOffType.from(1 == detailedInformation.climateState.isRearDefrosterOn)); + updateState(TeslascopeBindingConstants.CHANNEL_LEFT_SEAT_HEATER, + new DecimalType(detailedInformation.climateState.seatHeaterLeft)); + updateState(TeslascopeBindingConstants.CHANNEL_CENTER_REAR_SEAT_HEATER, + new DecimalType(detailedInformation.climateState.seatHeaterRearCenter)); + updateState(TeslascopeBindingConstants.CHANNEL_LEFT_REAR_SEAT_HEATER, + new DecimalType(detailedInformation.climateState.seatHeaterRearLeft)); + updateState(TeslascopeBindingConstants.CHANNEL_RIGHT_REAR_SEAT_HEATER, + new DecimalType(detailedInformation.climateState.seatHeaterRearRight)); + updateState(TeslascopeBindingConstants.CHANNEL_RIGHT_SEAT_HEATER, + new DecimalType(detailedInformation.climateState.seatHeaterRight)); + updateState(TeslascopeBindingConstants.CHANNEL_SIDE_MIRROR_HEATERS, + OnOffType.from(1 == detailedInformation.climateState.sideMirrorHeaters)); + updateState(TeslascopeBindingConstants.CHANNEL_SMARTPRECONDITIONG, + OnOffType.from(1 == detailedInformation.climateState.smartPreconditioning)); + updateState(TeslascopeBindingConstants.CHANNEL_STEERING_WHEEL_HEATER, + OnOffType.from(1 == detailedInformation.climateState.steeringWheelHeater)); + updateState(TeslascopeBindingConstants.CHANNEL_WIPER_BLADE_HEATER, + OnOffType.from(1 == detailedInformation.climateState.wiperBladeHeater)); + updateState(TeslascopeBindingConstants.CHANNEL_DRIVER_TEMP, + new QuantityType<>(detailedInformation.climateState.driverTempSetting, SIUnits.CELSIUS)); + updateState(TeslascopeBindingConstants.CHANNEL_INSIDE_TEMP, + new QuantityType<>(detailedInformation.climateState.insideTemp, SIUnits.CELSIUS)); + updateState(TeslascopeBindingConstants.CHANNEL_OUTSIDE_TEMP, + new QuantityType<>(detailedInformation.climateState.outsideTemp, SIUnits.CELSIUS)); + updateState(TeslascopeBindingConstants.CHANNEL_PASSENGER_TEMP, + new QuantityType<>(detailedInformation.climateState.passengerTempSetting, SIUnits.CELSIUS)); + updateState(TeslascopeBindingConstants.CHANNEL_FAN, + new DecimalType(detailedInformation.climateState.fanStatus)); + updateState(TeslascopeBindingConstants.CHANNEL_LEFT_TEMP_DIRECTION, + new DecimalType(detailedInformation.climateState.leftTempDirection)); + updateState(TeslascopeBindingConstants.CHANNEL_MAX_AVAILABLE_TEMP, + new QuantityType<>(detailedInformation.climateState.maxAvailTemp, SIUnits.CELSIUS)); + updateState(TeslascopeBindingConstants.CHANNEL_MIN_AVAILABLE_TEMP, + new QuantityType<>(detailedInformation.climateState.minAvailTemp, SIUnits.CELSIUS)); + updateState(TeslascopeBindingConstants.CHANNEL_RIGHT_TEMP_DIRECTION, + new DecimalType(detailedInformation.climateState.rightTempDirection)); + + // drive state + updateState(TeslascopeBindingConstants.CHANNEL_HEADING, + new DecimalType(detailedInformation.driveState.heading)); + updateState(TeslascopeBindingConstants.CHANNEL_LOCATION, new PointType( + detailedInformation.driveState.latitude + "," + detailedInformation.driveState.longitude)); + updateState(TeslascopeBindingConstants.CHANNEL_POWER, + new QuantityType<>(detailedInformation.driveState.power, MetricPrefix.KILO(Units.WATT))); + updateState(TeslascopeBindingConstants.CHANNEL_SHIFT_STATE, + new StringType(detailedInformation.driveState.shiftState)); + updateState(TeslascopeBindingConstants.CHANNEL_SPEED, + new QuantityType<>(detailedInformation.driveState.speed, ImperialUnits.MILES_PER_HOUR)); + + // vehicle state + updateState(TeslascopeBindingConstants.CHANNEL_DOOR_LOCK, + OnOffType.from(1 == detailedInformation.vehicleState.locked)); + updateState(TeslascopeBindingConstants.CHANNEL_SENTRY_MODE, + OnOffType.from(1 == detailedInformation.vehicleState.sentryMode)); + updateState(TeslascopeBindingConstants.CHANNEL_VALET_MODE, + OnOffType.from(1 == detailedInformation.vehicleState.valetMode)); + updateState(TeslascopeBindingConstants.CHANNEL_SOFTWARE_UPDATE_AVAILABLE, + OnOffType.from(!"".equals(detailedInformation.vehicleState.softwareUpdateStatus))); + updateState(TeslascopeBindingConstants.CHANNEL_SOFTWARE_UPDATE_STATUS, + new StringType(detailedInformation.vehicleState.softwareUpdateStatus)); + updateState(TeslascopeBindingConstants.CHANNEL_SOFTWARE_UPDATE_VERSION, + new StringType(detailedInformation.vehicleState.softwareUpdateVersion)); + updateState(TeslascopeBindingConstants.CHANNEL_SUNROOF_STATE, + new StringType(detailedInformation.vehicleState.sunRoofState)); + updateState(TeslascopeBindingConstants.CHANNEL_SUNROOF, + new DecimalType(detailedInformation.vehicleState.sunRoofPercentOpen)); + updateState(TeslascopeBindingConstants.CHANNEL_HOMELINK, + OnOffType.from(1 == detailedInformation.vehicleState.homelinkNearby)); + updateState(TeslascopeBindingConstants.CHANNEL_TPMS_FL, + new QuantityType<>(detailedInformation.vehicleState.tpmsPressureFL, Units.BAR)); + updateState(TeslascopeBindingConstants.CHANNEL_TPMS_FR, + new QuantityType<>(detailedInformation.vehicleState.tpmsPressureFR, Units.BAR)); + updateState(TeslascopeBindingConstants.CHANNEL_TPMS_RL, + new QuantityType<>(detailedInformation.vehicleState.tpmsPressureRL, Units.BAR)); + updateState(TeslascopeBindingConstants.CHANNEL_TPMS_RR, + new QuantityType<>(detailedInformation.vehicleState.tpmsPressureRR, Units.BAR)); + updateState(TeslascopeBindingConstants.CHANNEL_TPMS_SOFT_WARNING_FL, + OnOffType.from(1 == detailedInformation.vehicleState.tpmsSoftWarningFL)); + updateState(TeslascopeBindingConstants.CHANNEL_TPMS_SOFT_WARNING_FR, + OnOffType.from(1 == detailedInformation.vehicleState.tpmsSoftWarningFR)); + updateState(TeslascopeBindingConstants.CHANNEL_TPMS_SOFT_WARNING_RL, + OnOffType.from(1 == detailedInformation.vehicleState.tpmsSoftWarningRL)); + updateState(TeslascopeBindingConstants.CHANNEL_TPMS_SOFT_WARNING_RR, + OnOffType.from(1 == detailedInformation.vehicleState.tpmsSoftWarningRR)); + updateState(TeslascopeBindingConstants.CHANNEL_DRIVER_FRONT_DOOR, + (1 == detailedInformation.vehicleState.df) ? OpenClosedType.OPEN : OpenClosedType.CLOSED); + updateState(TeslascopeBindingConstants.CHANNEL_DRIVER_REAR_DOOR, + (1 == detailedInformation.vehicleState.dr) ? OpenClosedType.OPEN : OpenClosedType.CLOSED); + updateState(TeslascopeBindingConstants.CHANNEL_PASSENGER_FRONT_DOOR, + (1 == detailedInformation.vehicleState.pf) ? OpenClosedType.OPEN : OpenClosedType.CLOSED); + updateState(TeslascopeBindingConstants.CHANNEL_PASSENGER_REAR_DOOR, + (1 == detailedInformation.vehicleState.pr) ? OpenClosedType.OPEN : OpenClosedType.CLOSED); + updateState(TeslascopeBindingConstants.CHANNEL_FRONT_TRUNK, + OnOffType.from(1 == detailedInformation.vehicleState.ft)); + updateState(TeslascopeBindingConstants.CHANNEL_REAR_TRUNK, + OnOffType.from(1 == detailedInformation.vehicleState.rt)); + } + + // virtual items + updateState(TeslascopeBindingConstants.CHANNEL_HONK_HORN, OnOffType.OFF); + updateState(TeslascopeBindingConstants.CHANNEL_FLASH_LIGHTS, OnOffType.OFF); + } + + protected void setAutoConditioning(boolean b) + throws TeslascopeCommunicationException, TeslascopeAuthenticationException { + webTargets.sendCommand(config.publicID, config.apiKey, b ? "startAC" : "stopAC"); + } + + protected void charge(boolean b) throws TeslascopeCommunicationException, TeslascopeAuthenticationException { + webTargets.sendCommand(config.publicID, config.apiKey, b ? "startCharging" : "stopCharging"); + } + + protected void chargeDoor(boolean b) throws TeslascopeCommunicationException, TeslascopeAuthenticationException { + webTargets.sendCommand(config.publicID, config.apiKey, b ? "openChargeDoor" : "closeChargeDoor"); + } + + protected void flashLights() throws TeslascopeCommunicationException, TeslascopeAuthenticationException { + webTargets.sendCommand(config.publicID, config.apiKey, "flashLights"); + updateState(TeslascopeBindingConstants.CHANNEL_FLASH_LIGHTS, OnOffType.OFF); + } + + protected void honkHorn() throws TeslascopeCommunicationException, TeslascopeAuthenticationException { + webTargets.sendCommand(config.publicID, config.apiKey, "honkHorn"); + updateState(TeslascopeBindingConstants.CHANNEL_HONK_HORN, OnOffType.OFF); + } + + protected void lock(boolean b) throws TeslascopeCommunicationException, TeslascopeAuthenticationException { + webTargets.sendCommand(config.publicID, config.apiKey, b ? "lock" : "unlock"); + } + + protected void openFrunk() throws TeslascopeCommunicationException, TeslascopeAuthenticationException { + webTargets.sendCommand(config.publicID, config.apiKey, "openFrunk"); + } + + protected void openTrunk() throws TeslascopeCommunicationException, TeslascopeAuthenticationException { + webTargets.sendCommand(config.publicID, config.apiKey, "openTrunk"); + } + + protected void sentry(boolean b) throws TeslascopeCommunicationException, TeslascopeAuthenticationException { + webTargets.sendCommand(config.publicID, config.apiKey, b ? "enableSentryMode" : "disableSentryMode"); + } +} diff --git a/bundles/org.openhab.binding.teslascope/src/main/java/org/openhab/binding/teslascope/internal/TeslascopeHandlerFactory.java b/bundles/org.openhab.binding.teslascope/src/main/java/org/openhab/binding/teslascope/internal/TeslascopeHandlerFactory.java new file mode 100644 index 0000000000000..26a0451f8b80a --- /dev/null +++ b/bundles/org.openhab.binding.teslascope/src/main/java/org/openhab/binding/teslascope/internal/TeslascopeHandlerFactory.java @@ -0,0 +1,68 @@ +/** + * Copyright (c) 2010-2024 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.teslascope.internal; + +import static org.openhab.binding.teslascope.internal.TeslascopeBindingConstants.*; + +import java.util.Set; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jetty.client.HttpClient; +import org.openhab.core.io.net.http.HttpClientFactory; +import org.openhab.core.thing.Thing; +import org.openhab.core.thing.ThingTypeUID; +import org.openhab.core.thing.binding.BaseThingHandlerFactory; +import org.openhab.core.thing.binding.ThingHandler; +import org.openhab.core.thing.binding.ThingHandlerFactory; +import org.osgi.service.component.ComponentContext; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; + +/** + * The {@link TeslascopeHandlerFactory} is responsible for creating things and thing + * handlers. + * + * @author Paul Smedley - Initial contribution + */ +@NonNullByDefault +@Component(configurationPid = "binding.teslascope", service = ThingHandlerFactory.class) +public class TeslascopeHandlerFactory extends BaseThingHandlerFactory { + + private static final Set SUPPORTED_THING_TYPES_UIDS = Set.of(TESLASCOPE_THING); + + private final HttpClient httpClient; + + @Activate + public TeslascopeHandlerFactory(@Reference HttpClientFactory httpClientFactory, ComponentContext componentContext) { + super.activate(componentContext); + this.httpClient = httpClientFactory.getCommonHttpClient(); + } + + @Override + public boolean supportsThingType(ThingTypeUID thingTypeUID) { + return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); + } + + @Override + protected @Nullable ThingHandler createHandler(Thing thing) { + ThingTypeUID thingTypeUID = thing.getThingTypeUID(); + + if (TESLASCOPE_THING.equals(thingTypeUID)) { + return new TeslascopeHandler(thing, httpClient); + } + + return null; + } +} diff --git a/bundles/org.openhab.binding.teslascope/src/main/java/org/openhab/binding/teslascope/internal/TeslascopeWebTargets.java b/bundles/org.openhab.binding.teslascope/src/main/java/org/openhab/binding/teslascope/internal/TeslascopeWebTargets.java new file mode 100644 index 0000000000000..f0456149806d4 --- /dev/null +++ b/bundles/org.openhab.binding.teslascope/src/main/java/org/openhab/binding/teslascope/internal/TeslascopeWebTargets.java @@ -0,0 +1,83 @@ +/** + * Copyright (c) 2010-2024 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.teslascope.internal; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.client.api.ContentResponse; +import org.eclipse.jetty.client.api.Request; +import org.eclipse.jetty.http.HttpMethod; +import org.eclipse.jetty.http.HttpStatus; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Handles performing the actual HTTP requests for communicating with the TeslascopeAPI. + * + * @author Paul Smedley - Initial Contribution + * + */ +@NonNullByDefault +public class TeslascopeWebTargets { + private static final int TIMEOUT_MS = 30000; + private static final String BASE_URI = "https://teslascope.com/api/vehicle/"; + private final Logger logger = LoggerFactory.getLogger(TeslascopeWebTargets.class); + private HttpClient httpClient; + + public TeslascopeWebTargets(HttpClient httpClient) { + this.httpClient = httpClient; + } + + public String getDetailedInformation(String publicID, String apiKey) + throws TeslascopeCommunicationException, TeslascopeAuthenticationException { + return invoke(BASE_URI + publicID + "/detailed?api_key=" + apiKey); + } + + public void sendCommand(String publicID, String apiKey, String command) + throws TeslascopeCommunicationException, TeslascopeAuthenticationException { + invoke(BASE_URI + publicID + "/command/" + command + "?api_key=" + apiKey); + return; + } + + private String invoke(String uri) throws TeslascopeCommunicationException, TeslascopeAuthenticationException { + logger.debug("Calling url: {}", uri); + String jsonResponse = ""; + int status = 0; + try { + Request request = httpClient.newRequest(uri).method(HttpMethod.GET).timeout(TIMEOUT_MS, + TimeUnit.MILLISECONDS); + if (logger.isTraceEnabled()) { + logger.trace("{} request for {}", HttpMethod.GET, uri); + } + ContentResponse response = request.send(); + status = response.getStatus(); + jsonResponse = response.getContentAsString(); + logger.trace("JSON response: '{}'", jsonResponse); + if (status == HttpStatus.UNAUTHORIZED_401) { + throw new TeslascopeAuthenticationException("Unauthorized"); + } + if (!HttpStatus.isSuccess(status)) { + throw new TeslascopeCommunicationException( + String.format("Teslascope returned error <%d> while invoking %s", status, uri)); + } + } catch (TimeoutException | ExecutionException | InterruptedException ex) { + throw new TeslascopeCommunicationException(ex.getLocalizedMessage(), ex); + } + + return jsonResponse; + } +} diff --git a/bundles/org.openhab.binding.teslascope/src/main/java/org/openhab/binding/teslascope/internal/api/ChargeState.java b/bundles/org.openhab.binding.teslascope/src/main/java/org/openhab/binding/teslascope/internal/api/ChargeState.java new file mode 100644 index 0000000000000..23cd5a6d7243e --- /dev/null +++ b/bundles/org.openhab.binding.teslascope/src/main/java/org/openhab/binding/teslascope/internal/api/ChargeState.java @@ -0,0 +1,74 @@ +/** + * Copyright (c) 2010-2024 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.teslascope.internal.api; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +import com.google.gson.annotations.SerializedName; + +/** + * Class for holding the set of parameters used to read the controller variables. + * + * @author Paul Smedley - Initial Contribution + * + */ +@NonNullByDefault +public class ChargeState { + @SerializedName("battery_level") + public int batteryLevel; + + @SerializedName("usable_battery_level") + public int usableBatteryLevel; + + @SerializedName("battery_range") + public float batteryRange; + + @SerializedName("est_battery_range") + public float estBatteryRange; + + @SerializedName("charge_enable_request") + public int chargeEnableRequest; + + @SerializedName("charge_energy_added") + public float chargeEnergyAdded; + + @SerializedName("charge_limit_soc") + public int chargeLimitSoc; + + @SerializedName("charge_port_door_open") + public int chargePortDoorOpen; + + @SerializedName("charge_rate") + public float chargeRate; + + @SerializedName("charger_power") + public int chargerPower; + + @SerializedName("charger_voltage") + public int chargerVoltage; + + @SerializedName("charging_state") + public String chargingState = ""; + + @SerializedName("time_to_full_charge") + public float timeToFullCharge; + + @SerializedName("scheduled_charging_pending") + public int scheduledChargingPending; + + @SerializedName("scheduled_charging_start_time") + public String scheduledChargingStartTime = " "; + + private ChargeState() { + } +} diff --git a/bundles/org.openhab.binding.teslascope/src/main/java/org/openhab/binding/teslascope/internal/api/ClimateState.java b/bundles/org.openhab.binding.teslascope/src/main/java/org/openhab/binding/teslascope/internal/api/ClimateState.java new file mode 100644 index 0000000000000..5bb4750739178 --- /dev/null +++ b/bundles/org.openhab.binding.teslascope/src/main/java/org/openhab/binding/teslascope/internal/api/ClimateState.java @@ -0,0 +1,99 @@ +/** + * Copyright (c) 2010-2024 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.teslascope.internal.api; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +import com.google.gson.annotations.SerializedName; + +/** + * Class for holding the set of parameters used to read the controller variables. + * + * @author Paul Smedley - Initial Contribution + * + */ +@NonNullByDefault +public class ClimateState { + // climate_state + @SerializedName("is_auto_conditioning_on") + public int isAutoConditioningOn; + + @SerializedName("is_climate_on") + public int isClimateOn; + + @SerializedName("is_front_defroster_on") + public int isFrontDefrosterOn; + + @SerializedName("is_preconditioning") + public int isPreconditioning; + + @SerializedName("is_rear_defroster_on") + public int isRearDefrosterOn; + + @SerializedName("seat_heater_left") + public int seatHeaterLeft; + + @SerializedName("seat_heater_rear_center") + public int seatHeaterRearCenter; + + @SerializedName("seat_heater_rear_left") + public int seatHeaterRearLeft; + + @SerializedName("seat_heater_rear_right") + public int seatHeaterRearRight; + + @SerializedName("seat_heater_right") + public int seatHeaterRight; + + @SerializedName("side_mirror_heaters") + public int sideMirrorHeaters; + + @SerializedName("smart_preconditioning") + public int smartPreconditioning; + + @SerializedName("steering_wheel_heater") + public int steeringWheelHeater; + + @SerializedName("wiper_blade_heater") + public int wiperBladeHeater; + + @SerializedName("driver_temp_setting") + public float driverTempSetting; + + @SerializedName("inside_temp") + public float insideTemp; + + @SerializedName("outside_temp") + public float outsideTemp; + + @SerializedName("passenger_temp_setting") + public float passengerTempSetting; + + @SerializedName("fan_status") + public float fanStatus; + + @SerializedName("left_temp_direction") + public int leftTempDirection; + + @SerializedName("max_avail_temp") + public float maxAvailTemp; + + @SerializedName("min_avail_temp") + public float minAvailTemp; + + @SerializedName("right_temp_direction") + public int rightTempDirection; + + private ClimateState() { + } +} diff --git a/bundles/org.openhab.binding.teslascope/src/main/java/org/openhab/binding/teslascope/internal/api/DetailedInformation.java b/bundles/org.openhab.binding.teslascope/src/main/java/org/openhab/binding/teslascope/internal/api/DetailedInformation.java new file mode 100644 index 0000000000000..b8c49f106c76a --- /dev/null +++ b/bundles/org.openhab.binding.teslascope/src/main/java/org/openhab/binding/teslascope/internal/api/DetailedInformation.java @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2010-2024 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.teslascope.internal.api; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +import com.google.gson.annotations.SerializedName; + +/** + * Class for holding the set of parameters used to read the controller variables. + * + * @author Paul Smedley - Initial Contribution + * + */ + +@NonNullByDefault +public class DetailedInformation { + public String vin = ""; + public String name = ""; + public String state = ""; + public double odometer; + + @SerializedName("vehicle_state") + public @NonNullByDefault({}) VehicleState vehicleState; + + @SerializedName("climate_state") + public @NonNullByDefault({}) ClimateState climateState; + + @SerializedName("charge_state") + public @NonNullByDefault({}) ChargeState chargeState; + + @SerializedName("drive_state") + public @NonNullByDefault({}) DriveState driveState; + + private DetailedInformation() { + } +} diff --git a/bundles/org.openhab.binding.teslascope/src/main/java/org/openhab/binding/teslascope/internal/api/DriveState.java b/bundles/org.openhab.binding.teslascope/src/main/java/org/openhab/binding/teslascope/internal/api/DriveState.java new file mode 100644 index 0000000000000..353f9afab6d07 --- /dev/null +++ b/bundles/org.openhab.binding.teslascope/src/main/java/org/openhab/binding/teslascope/internal/api/DriveState.java @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2010-2024 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.teslascope.internal.api; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +import com.google.gson.annotations.SerializedName; + +/** + * Class for holding the set of parameters used to read the controller variables. + * + * @author Paul Smedley - Initial Contribution + * + */ +@NonNullByDefault +public class DriveState { + // drive state + public int heading; + public float latitude; + public float longitude; + + @SerializedName("shift_state") + public String shiftState = ""; + + public float power; + public float speed = 0; + + private DriveState() { + } +} diff --git a/bundles/org.openhab.binding.teslascope/src/main/java/org/openhab/binding/teslascope/internal/api/VehicleState.java b/bundles/org.openhab.binding.teslascope/src/main/java/org/openhab/binding/teslascope/internal/api/VehicleState.java new file mode 100644 index 0000000000000..319eed664a09d --- /dev/null +++ b/bundles/org.openhab.binding.teslascope/src/main/java/org/openhab/binding/teslascope/internal/api/VehicleState.java @@ -0,0 +1,96 @@ +/** + * Copyright (c) 2010-2024 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.teslascope.internal.api; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +import com.google.gson.annotations.SerializedName; + +/** + * Class for holding the set of parameters used to read the controller variables. + * + * @author Paul Smedley - Initial Contribution + * + */ +@NonNullByDefault +public class VehicleState { + // vehicle_state + public int locked; + + @SerializedName("sentry_mode") + public int sentryMode; + + @SerializedName("valet_mode") + public int valetMode; + + @SerializedName("software_update_status") + public String softwareUpdateStatus = ""; + + @SerializedName("software_update_version") + public String softwareUpdateVersion = ""; + + @SerializedName("fd_window") + public int fdWindow; + + @SerializedName("fp_window") + public int fpWindow; + + @SerializedName("rd_window") + public int rdWindow; + + @SerializedName("rp_window") + public int rpWindow; + + @SerializedName("sun_roof_state") + public String sunRoofState = ""; + + @SerializedName("sunRoofPercentOpen") + public int sunRoofPercentOpen; + + @SerializedName("homelink_nearby") + public int homelinkNearby; + + @SerializedName("tpms_pressure_fl") + public double tpmsPressureFL; + + @SerializedName("tpms_pressure_fr") + public double tpmsPressureFR; + + @SerializedName("tpms_pressure_rl") + public double tpmsPressureRL; + + @SerializedName("tpms_pressure_rr") + public double tpmsPressureRR; + + @SerializedName("tpms_soft_warning_fl") + public int tpmsSoftWarningFL; + + @SerializedName("tpms_soft_warning_fr") + public int tpmsSoftWarningFR; + + @SerializedName("tpms_soft_warning_rl") + public int tpmsSoftWarningRL; + + @SerializedName("tpms_soft_warning_rr") + public int tpmsSoftWarningRR; + + public int df; + public int dr; + public int pf; + public int pr; + public int ft; + public int rt; + + private VehicleState() { + } +} diff --git a/bundles/org.openhab.binding.teslascope/src/main/resources/OH-INF/addon/addon.xml b/bundles/org.openhab.binding.teslascope/src/main/resources/OH-INF/addon/addon.xml new file mode 100644 index 0000000000000..6684560bb52cd --- /dev/null +++ b/bundles/org.openhab.binding.teslascope/src/main/resources/OH-INF/addon/addon.xml @@ -0,0 +1,11 @@ + + + + binding + Teslascope + This is the binding for Teslascope. + cloud + + diff --git a/bundles/org.openhab.binding.teslascope/src/main/resources/OH-INF/i18n/teslascope.properties b/bundles/org.openhab.binding.teslascope/src/main/resources/OH-INF/i18n/teslascope.properties new file mode 100644 index 0000000000000..c72a8a65ffc97 --- /dev/null +++ b/bundles/org.openhab.binding.teslascope/src/main/resources/OH-INF/i18n/teslascope.properties @@ -0,0 +1,179 @@ +# add-on + +addon.teslascope.name = Teslascope +addon.teslascope.description = This is the binding for Teslascope. + +# thing types + +thing-type.teslascope.vehicle.label = Teslascope +thing-type.teslascope.vehicle.description = Access to Tesla Vehicle data via the Teslascope developer API + +# thing types config + +thing-type.config.teslascope.vehicle.apiKey.label = apiKey +thing-type.config.teslascope.vehicle.apiKey.description = apiKey provided by Teslascope +thing-type.config.teslascope.vehicle.publicID.label = Vehicle Public ID +thing-type.config.teslascope.vehicle.publicID.description = Vehicle public ID listed in Teslascope +thing-type.config.teslascope.vehicle.refreshInterval.label = Refresh Interval +thing-type.config.teslascope.vehicle.refreshInterval.description = Interval the API is polled in sec. + +# channel types + +channel-type.teslascope.auto-conditioning.label = Auto Conditioning +channel-type.teslascope.auto-conditioning.description = Turns on auto-conditioning (a/c or heating) +channel-type.teslascope.battery-level.label = Battery Level +channel-type.teslascope.battery-level.description = Vehicle Battery Level +channel-type.teslascope.battery-range.label = Battery Range +channel-type.teslascope.battery-range.description = Range of the battery +channel-type.teslascope.center-rear-seat-heater.label = Center Rear Seat Heater +channel-type.teslascope.center-rear-seat-heater.description = Indicates if the center rear seat heater is switched on +channel-type.teslascope.charge-energy-added.label = Charge Energy Added +channel-type.teslascope.charge-energy-added.description = Energy added, in kWh, during the last charging session +channel-type.teslascope.charge-limit-soc-standard.label = Charge Limit SOC Standard +channel-type.teslascope.charge-limit-soc-standard.description = Standard charging limit of the vehicle, in % +channel-type.teslascope.charge-port.label = Charge Port +channel-type.teslascope.charge-port.description = Open the Charge Port (ON) or indicates the state of the Charge Port (ON/OFF if Open/Closed) +channel-type.teslascope.charge-rate.label = Charge Rate +channel-type.teslascope.charge-rate.description = Distance per hour charging rate +channel-type.teslascope.charge.label = Charge +channel-type.teslascope.charge.description = Start (ON) or stop (OFF) charging +channel-type.teslascope.charger-power.label = Charger Power +channel-type.teslascope.charger-power.description = Power actually delivered by the charger +channel-type.teslascope.charger-voltage.label = Charger Voltage +channel-type.teslascope.charger-voltage.description = Voltage (V) actually presented by the charger +channel-type.teslascope.charging-state.label = Charging State +channel-type.teslascope.charging-state.description = Charging State +channel-type.teslascope.climate.label = Climate +channel-type.teslascope.climate.description = Climate status indicator +channel-type.teslascope.door-lock.label = Door Lock +channel-type.teslascope.door-lock.description = Lock or unlock the car +channel-type.teslascope.driver-front-door.label = Driver Front Door +channel-type.teslascope.driver-front-door.description = Indicates if the front door at the driver's side is opened +channel-type.teslascope.driver-rear-door.label = Driver Rear Door +channel-type.teslascope.driver-rear-door.description = Indicates if the rear door at the driver's side is opened +channel-type.teslascope.driver-temp.label = Driver Temperature +channel-type.teslascope.driver-temp.description = Indicates the auto conditioning temperature set at the driver's side +channel-type.teslascope.estimated-battery-range.label = Estimated Battery Range +channel-type.teslascope.estimated-battery-range.description = Estimated battery range +channel-type.teslascope.fan.label = Fan +channel-type.teslascope.fan.description = Indicates the speed (0-7) of the fan +channel-type.teslascope.flash-lights.label = Flash Lights +channel-type.teslascope.flash-lights.description = Flash the lights of the car (when ON is received) +channel-type.teslascope.front-defroster.label = Front Defroster +channel-type.teslascope.front-defroster.description = Indicates if the front defroster is enabled +channel-type.teslascope.front-trunk.label = Front Trunk +channel-type.teslascope.front-trunk.description = Indicates if the front trunk is opened, or open the front trunk when ON is received +channel-type.teslascope.heading.label = Heading +channel-type.teslascope.heading.description = Indicates the (compass) heading of the car, in 0-360 degrees +channel-type.teslascope.homelink.label = Homelink Nearby +channel-type.teslascope.homelink.description = Indicates if the Home Link is nearby +channel-type.teslascope.honk-horn.label = Honk the Horn +channel-type.teslascope.honk-horn.description = Honk the horn of the vehicle, when ON is received +channel-type.teslascope.inside-temp.label = Inside Temperature +channel-type.teslascope.inside-temp.description = Indicates the inside temperature of the vehicle +channel-type.teslascope.left-rear-seat-heater.label = Left Rear Seat Heater +channel-type.teslascope.left-rear-seat-heater.description = Indicates if the left rear seat heater is switched on +channel-type.teslascope.left-seat-heater.label = Left Seat Heater +channel-type.teslascope.left-seat-heater.description = Indicates if the left seat heater is switched on +channel-type.teslascope.left-temp-direction.label = Left Temperature Direction +channel-type.teslascope.left-temp-direction.description = Not documented / To be defined +channel-type.teslascope.location.label = Location +channel-type.teslascope.location.description = The actual position of the vehicle +channel-type.teslascope.max-available-temp.label = Maximum Temperature +channel-type.teslascope.max-available-temp.description = Indicates the maximum inside temperature of the vehicle +channel-type.teslascope.min-available-temp.label = Minimum Temperature +channel-type.teslascope.min-available-temp.description = Indicates the minimal inside temperature of the vehicle +channel-type.teslascope.odometer.label = Odometer +channel-type.teslascope.odometer.description = Vehicle Odometer +channel-type.teslascope.outside-temp.label = Outside Temperature +channel-type.teslascope.outside-temp.description = Indicates the outside temperature of the vehicle +channel-type.teslascope.passenger-front-door.label = Passenger Front Door +channel-type.teslascope.passenger-front-door.description = Indicates if the front door at the passenger's side is opened +channel-type.teslascope.passenger-rear-door.label = Passenger Rear Door +channel-type.teslascope.passenger-rear-door.description = Indicates if the rear door at the passenger's side is opened +channel-type.teslascope.passenger-temp.label = Passenger Temperature +channel-type.teslascope.passenger-temp.description = Indicates the auto conditioning temperature set at the passenger's side +channel-type.teslascope.power.label = Power +channel-type.teslascope.power.description = Net kW flowing in (+) or out (-) of the battery +channel-type.teslascope.preconditioning.label = Preconditioning +channel-type.teslascope.preconditioning.description = Indicates if preconditioning is activated +channel-type.teslascope.rear-defroster.label = Rear Defroster +channel-type.teslascope.rear-defroster.description = Indicates if the rear defroster is enabled +channel-type.teslascope.rear-trunk.label = Rear Trunk +channel-type.teslascope.rear-trunk.description = Indicates if the rear trunk is opened, or open/close the rear trunk when ON/OFF is received +channel-type.teslascope.right-rear-seat-heater.label = Right Rear Seat Heater +channel-type.teslascope.right-rear-seat-heater.description = Indicates if the right rear seat heater is switched on +channel-type.teslascope.right-seat-heater.label = Right Seat Heater +channel-type.teslascope.right-seat-heater.description = Indicates if the right seat heater is switched on +channel-type.teslascope.right-temp-direction.label = Right Temperature Direction +channel-type.teslascope.right-temp-direction.description = Not documented / To be defined +channel-type.teslascope.scheduled-charging-pending.label = Scheduled Charging Pending +channel-type.teslascope.scheduled-charging-pending.description = Indicates if a scheduled charging session is still pending +channel-type.teslascope.scheduled-charging-start.label = Scheduled Charging Start +channel-type.teslascope.scheduled-charging-start.description = Indicates when the scheduled charging session will start, in yyyy-MM-dd'T'HH:mm:ss format +channel-type.teslascope.sentry-mode.label = Sentry Mode +channel-type.teslascope.sentry-mode.description = Activates or deactivates sentry mode +channel-type.teslascope.shift-state.label = Shift State +channel-type.teslascope.shift-state.description = Indicates the state of the transmission, “P”, “D”, “R”, or “N” +channel-type.teslascope.side-mirror-heaters.label = Side Mirror Heaters +channel-type.teslascope.side-mirror-heaters.description = Indicates if the side mirror heaters are switched on +channel-type.teslascope.smart-preconditioning.label = Smart Preconditioning +channel-type.teslascope.smart-preconditioning.description = Indicates if smart preconditioning is switched on +channel-type.teslascope.software-update-available.label = Update Available +channel-type.teslascope.software-update-available.description = Car software or map update available +channel-type.teslascope.software-update-status.label = Update Status +channel-type.teslascope.software-update-status.description = Car software or map update status +channel-type.teslascope.software-update-version.label = Update Version +channel-type.teslascope.software-update-version.description = Car software or map version to update to +channel-type.teslascope.speed.label = Speed +channel-type.teslascope.speed.description = Vehicle speed +channel-type.teslascope.steering-wheel-heater.label = Steering Wheel Heater +channel-type.teslascope.steering-wheel-heater.description = Turns On/Off the steering wheel heater +channel-type.teslascope.sunroof-state.label = Sunroof State +channel-type.teslascope.sunroof-state.description = Valid states are “unknown”, “open”, “closed”, “vent”, “comfort”. Accepts commands "close" and "vent". +channel-type.teslascope.sunroof.label = Sunroof +channel-type.teslascope.sunroof.description = Indicates the opening state of the sunroof (0% closed, 100% fully open) +channel-type.teslascope.time-to-full-charge.label = Time To Full Charge +channel-type.teslascope.time-to-full-charge.description = Number of hours to fully charge the battery +channel-type.teslascope.tpms-pressure-fl.label = Tyre Pressure FL +channel-type.teslascope.tpms-pressure-fl.description = Tyre Pressure Front Left +channel-type.teslascope.tpms-pressure-fr.label = Tyre Pressure FR +channel-type.teslascope.tpms-pressure-fr.description = Tyre Pressure Front Right +channel-type.teslascope.tpms-pressure-rl.label = Tyre Pressure RL +channel-type.teslascope.tpms-pressure-rl.description = Tyre Pressure Rear Left +channel-type.teslascope.tpms-pressure-rr.label = Tyre Pressure RR +channel-type.teslascope.tpms-pressure-rr.description = Tyre Pressure Rear Right +channel-type.teslascope.tpms-soft-warning-fl.label = Tyre Pressure Warning FL +channel-type.teslascope.tpms-soft-warning-fl.description = Tyre Pressure Front Left - warning for low pressure +channel-type.teslascope.tpms-soft-warning-fr.label = Tyre Pressure Warning FR +channel-type.teslascope.tpms-soft-warning-fr.description = Tyre Pressure Front Right - warning for low pressure +channel-type.teslascope.tpms-soft-warning-rl.label = Tyre Pressure Warning RL +channel-type.teslascope.tpms-soft-warning-rl.description = Tyre Pressure Rear Left - warning for low pressure +channel-type.teslascope.tpms-soft-warning-rr.label = Tyre Pressure Warning RR +channel-type.teslascope.tpms-soft-warning-rr.description = Tyre Pressure Rear Right - warning for low pressure +channel-type.teslascope.usable-battery-level.label = Usable Battery Level +channel-type.teslascope.usable-battery-level.description = Indicates the % of battery that can be used for vehicle functions like driving +channel-type.teslascope.valet-mode.label = Valet Mode +channel-type.teslascope.valet-mode.description = Enable or disable Valet Mode +channel-type.teslascope.vehicle-name.label = Name +channel-type.teslascope.vehicle-name.description = Vehicle Name +channel-type.teslascope.vehicle-state.label = Vehicle State +channel-type.teslascope.vehicle-state.description = Vehicle State +channel-type.teslascope.vin.label = VIN +channel-type.teslascope.vin.description = Vehicle Identification Number +channel-type.teslascope.wiper-blade-heater.label = Wiperblade Heater +channel-type.teslascope.wiper-blade-heater.description = Indicates if the wiperblade heater is switched on + +# thing types + +thing-type.teslascope.service.label = Teslascope +thing-type.teslascope.service.description = Access to Tesla Vehicle data via the Teslascope developer API + +# thing types config + +thing-type.config.teslascope.service.apiKey.label = apiKey +thing-type.config.teslascope.service.apiKey.description = apiKey provided by Teslascope +thing-type.config.teslascope.service.publicID.label = Vehicle Public ID +thing-type.config.teslascope.service.publicID.description = Vehicle public ID listed in Teslascope +thing-type.config.teslascope.service.refreshInterval.label = Refresh Interval +thing-type.config.teslascope.service.refreshInterval.description = Interval the API is polled in sec. diff --git a/bundles/org.openhab.binding.teslascope/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.teslascope/src/main/resources/OH-INF/thing/thing-types.xml new file mode 100644 index 0000000000000..f76aba92644d2 --- /dev/null +++ b/bundles/org.openhab.binding.teslascope/src/main/resources/OH-INF/thing/thing-types.xml @@ -0,0 +1,525 @@ + + + + + + Access to Tesla Vehicle data via the Teslascope developer API + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + apiKey provided by Teslascope + + + + Vehicle public ID listed in Teslascope + + + + Interval the API is polled in sec. + 60 + true + + + + + + String + + Vehicle Identification Number + + + + String + + Vehicle Name + + + + String + + Vehicle State + + + + Number:Length + + Vehicle Odometer + + + + Number:Dimensionless + + Vehicle Battery Level + + + + String + + Charging State + + + + Switch + + Car software or map update available + + + + String + + Car software or map update status + + + + String + + Car software or map version to update to + + + + Switch + + Turns on auto-conditioning (a/c or heating) + + + Number:Length + + Range of the battery + + + + Switch + + Indicates if the center rear seat heater is switched on + + + + Switch + + Start (ON) or stop (OFF) charging + + + Number:Energy + + Energy added, in kWh, during the last charging session + + + + Dimmer + + Standard charging limit of the vehicle, in % + + + + Switch + + Open the Charge Port (ON) or indicates the state of the Charge Port (ON/OFF if Open/Closed) + + + Number:Speed + + Distance per hour charging rate + + + + Number:Power + + Power actually delivered by the charger + + + + Number:ElectricPotential + + Voltage (V) actually presented by the charger + + + + Switch + + Climate status indicator + + + + Contact + + Indicates if the front door at the driver's side is opened + + + + Switch + + Lock or unlock the car + + + Contact + + Indicates if the rear door at the driver's side is opened + + + + Number:Temperature + + Indicates the auto conditioning temperature set at the driver's side + + + + Number:Length + + Estimated battery range + + + + Number + + Indicates the speed (0-7) of the fan + + + + Switch + + Flash the lights of the car (when ON is received) + + + Switch + + Indicates if the front defroster is enabled + + + + Switch + + Indicates if the front trunk is opened, or open the front trunk when ON is received + + + Number:Angle + + Indicates the (compass) heading of the car, in 0-360 degrees + + + + Switch + + Honk the horn of the vehicle, when ON is received + + + Switch + + Indicates if the Home Link is nearby + + + Number:Temperature + + Indicates the inside temperature of the vehicle + + + + Number + + Not documented / To be defined + + + + Location + + The actual position of the vehicle + + + + Switch + + Indicates if the left seat heater is switched on + + + + Switch + + Indicates if the left rear seat heater is switched on + + + + Number:Temperature + + Indicates the minimal inside temperature of the vehicle + + + + Number:Temperature + + Indicates the maximum inside temperature of the vehicle + + + + Number:Temperature + + Indicates the outside temperature of the vehicle + + + + Number + + Indicates the auto conditioning temperature set at the passenger's side + + + + Contact + + Indicates if the front door at the passenger's side is opened + + + + Contact + + Indicates if the rear door at the passenger's side is opened + + + + Number:Power + + Net kW flowing in (+) or out (-) of the battery + + + + Switch + + Indicates if preconditioning is activated + + + + Switch + + Indicates if the rear defroster is enabled + + + + Switch + + Indicates if the rear trunk is opened, or open/close the rear trunk when ON/OFF is received + + + Switch + + Indicates if the right seat heater is switched on + + + + Switch + + Indicates if the right rear seat heater is switched on + + + + Number + + Not documented / To be defined + + + + Switch + + Indicates if a scheduled charging session is still pending + + + + DateTime + + Indicates when the scheduled charging session will start, in yyyy-MM-dd'T'HH:mm:ss format + + + + Switch + + Activates or deactivates sentry mode + + + String + + Indicates the state of the transmission, “P”, “D”, “R”, or “N” + + + + Switch + + Indicates if the side mirror heaters are switched on + + + + Switch + + Indicates if smart preconditioning is switched on + + + + Number:Speed + + Vehicle speed + + + + Switch + + Turns On/Off the steering wheel heater + + + + String + + Valid states are “unknown”, “open”, “closed”, “vent”, “comfort”. Accepts commands "close" and "vent". + + + + Dimmer + + Indicates the opening state of the sunroof (0% closed, 100% fully open) + + + + Number + + Number of hours to fully charge the battery + + + + Number:Pressure + + Tyre Pressure Front Left + + + + Number:Pressure + + Tyre Pressure Front Right + + + + Number:Pressure + + Tyre Pressure Rear Left + + + + Number:Pressure + + Tyre Pressure Rear Right + + + + Switch + + Tyre Pressure Front Left - warning for low pressure + + + + Switch + + Tyre Pressure Front Right - warning for low pressure + + + + Switch + + Tyre Pressure Rear Left - warning for low pressure + + + + Switch + + Tyre Pressure Rear Right - warning for low pressure + + + + Number + + Indicates the % of battery that can be used for vehicle functions like driving + + + + Switch + + Enable or disable Valet Mode + + + Switch + + Indicates if the wiperblade heater is switched on + + + diff --git a/bundles/pom.xml b/bundles/pom.xml index 49293ac78ea89..1f26e09f2c2d3 100644 --- a/bundles/pom.xml +++ b/bundles/pom.xml @@ -406,6 +406,7 @@ org.openhab.binding.tellstick org.openhab.binding.tesla org.openhab.binding.teslapowerwall + org.openhab.binding.teslascope org.openhab.binding.tibber org.openhab.binding.tivo org.openhab.binding.touchwand