Skip to content

Commit

Permalink
Merge pull request #56 from alandtse/online_sensor
Browse files Browse the repository at this point in the history
feat: add online sensor
  • Loading branch information
alandtse committed Jan 27, 2020
2 parents 32a37b2 + 46e89be commit 948a6e1
Show file tree
Hide file tree
Showing 8 changed files with 143 additions and 36 deletions.
26 changes: 23 additions & 3 deletions teslajsonpy/battery_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
For more details about this api, please refer to the documentation at
https://github.com/zabuldon/teslajsonpy
"""
from typing import Dict, Text
from typing import Dict, Optional, Text

from teslajsonpy.vehicle import VehicleDevice

Expand All @@ -29,6 +29,7 @@ def __init__(self, data: Dict, controller) -> None:
self.type: Text = "battery sensor"
self.measurement: Text = "%"
self.hass_type: Text = "sensor"
self._device_class: Text = "battery"
self.name: Text = self._name()
self.uniq_name: Text = self._uniq_name()
self.bin_type: hex = 0x5
Expand All @@ -39,17 +40,30 @@ async def async_update(self) -> None:
data = self._controller.get_charging_params(self._id)
if data:
self.__battery_level = data["battery_level"]
self.__charging_state = data["charging_state"]
self.__charging_state = data["charging_state"] == "Charging"

@staticmethod
def has_battery() -> bool:
"""Return whether the device has a battery."""
return False
return True

def get_value(self) -> int:
"""Return the battery level."""
return self.__battery_level

def battery_level(self) -> int:
"""Return the battery level."""
return self.get_value()

def battery_charging(self) -> bool:
"""Return the battery level."""
return self.__charging_state

@property
def device_class(self) -> Text:
"""Return the HA device class."""
return self._device_class


class Range(VehicleDevice):
"""Home-Assistant class of the battery range for a Tesla VehicleDevice."""
Expand Down Expand Up @@ -78,6 +92,7 @@ def __init__(self, data: Dict, controller) -> None:
self.__rated = True
self.measurement = "LENGTH_MILES"
self.hass_type = "sensor"
self._device_class: Optional[Text] = None
self.name = self._name()
self.uniq_name = self._uniq_name()
self.bin_type = 0xA
Expand Down Expand Up @@ -112,3 +127,8 @@ def get_value(self):
if self.__rated:
return self.__battery_range
return self.__ideal_battery_range

@property
def device_class(self) -> Text:
"""Return the HA device class."""
return self._device_class
46 changes: 45 additions & 1 deletion teslajsonpy/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
For more details about this api, please refer to the documentation at
https://github.com/zabuldon/teslajsonpy
"""
from typing import Dict, Text

from teslajsonpy.vehicle import VehicleDevice


Expand All @@ -14,7 +16,7 @@ class ParkingSensor(VehicleDevice):
This is intended to be partially inherited by a Home-Assitant entity.
"""

def __init__(self, data, controller):
def __init__(self, data: Dict, controller):
"""Initialize the parking brake sensor.
Parameters
Expand All @@ -41,12 +43,16 @@ def __init__(self, data, controller):

self.uniq_name = self._uniq_name()
self.bin_type = 0x1
self.attrs: Dict[Text, Text] = {}

async def async_update(self):
"""Update the parking brake sensor."""
await super().async_update()
data = self._controller.get_drive_params(self._id)
if data:
self.attrs["shift_state"] = (
data["shift_state"] if data["shift_state"] else "P"
)
if not data["shift_state"] or data["shift_state"] == "P":
self.__state = True
else:
Expand Down Expand Up @@ -94,12 +100,14 @@ def __init__(self, data, controller):

self.uniq_name = self._uniq_name()
self.bin_type = 0x2
self.attrs: Dict[Text, Text] = {}

async def async_update(self):
"""Update the charger connection sensor."""
await super().async_update()
data = self._controller.get_charging_params(self._id)
if data:
self.attrs["charging_state"] = data["charging_state"]
if data["charging_state"] in ["Disconnected"]:
self.__state = False
else:
Expand All @@ -113,3 +121,39 @@ def get_value(self):
def has_battery():
"""Return whether the device has a battery."""
return False


class OnlineSensor(VehicleDevice):
"""Home-Assistant Online sensor class for a Tesla VehicleDevice."""

def __init__(self, data: Dict, controller) -> None:
"""Initialize the Online sensor.
Args:
data (Dict): The base state for a Tesla vehicle.
https://tesla-api.timdorr.com/vehicle/state/data
controller (Controller): The controller that controls updates to the Tesla API.
"""
super().__init__(data, controller)
self.__online_state: bool = None
self.type: Text = "online sensor"
self.hass_type = "binary_sensor"
self.name: Text = self._name()
self.uniq_name: Text = self._uniq_name()
self.attrs: Dict[Text, Text] = {}

async def async_update(self) -> None:
"""Update the battery state."""
await super().async_update()
self.__online_state = self._controller.car_online[self._vin]
self.attrs["state"] = self._controller.raw_online_state[self._vin]

@staticmethod
def has_battery() -> bool:
"""Return whether the device has a battery."""
return False

def get_value(self) -> bool:
"""Return the battery level."""
return self.__online_state
8 changes: 7 additions & 1 deletion teslajsonpy/charger.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
https://github.com/zabuldon/teslajsonpy
"""
import time
from typing import Dict, Text
from typing import Dict, Optional, Text

from teslajsonpy.vehicle import VehicleDevice

Expand Down Expand Up @@ -150,6 +150,7 @@ def __init__(self, data: Dict, controller) -> None:
self.__rated: bool = True
self.measurement: Text = "mi/hr"
self.hass_type: Text = "sensor"
self._device_class: Optional[Text] = None
self.name: Text = self._name()
self.uniq_name: Text = self._uniq_name()
self.bin_type: hex = 0xC
Expand Down Expand Up @@ -217,3 +218,8 @@ def charger_actual_current(self) -> float:
def charger_voltage(self) -> float:
"""Return the charging rate."""
return self.__charger_voltage

@property
def device_class(self) -> Text:
"""Return the HA device class."""
return self._device_class
7 changes: 7 additions & 0 deletions teslajsonpy/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
https://github.com/zabuldon/teslajsonpy
"""
import time
from typing import Text

from teslajsonpy.vehicle import VehicleDevice

Expand Down Expand Up @@ -166,6 +167,7 @@ def __init__(self, data, controller):
self.type = "temperature sensor"
self.measurement = "C"
self.hass_type = "sensor"
self._device_class: Text = "temperature"
self.name = self._name()
self.uniq_name = self._uniq_name()
self.bin_type = 0x4
Expand Down Expand Up @@ -194,3 +196,8 @@ async def async_update(self):
def has_battery():
"""Return whether the device has a battery."""
return False

@property
def device_class(self) -> Text:
"""Return the HA device class."""
return self._device_class
12 changes: 10 additions & 2 deletions teslajsonpy/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,13 @@ def __init__(
self.expiration: int = 0
self.access_token = None
self.head = None
self.refresh_token = None
self.refresh_token = refresh_token
self.websession = websession
self.token_refreshed = False
self.generate_oauth(email, password, refresh_token)
if access_token:
self.__sethead(access_token)
_LOGGER.debug("Connecting with existing access token")

def generate_oauth(
self, email: Text = None, password: Text = None, refresh_token: Text = None
Expand Down Expand Up @@ -77,9 +78,13 @@ def generate_oauth(
elif refresh_token:
self.oauth["grant_type"] = "refresh_token"
self.oauth["refresh_token"] = refresh_token
elif not refresh_token:
raise IncompleteCredentials(
"Missing oauth authentication details: refresh token."
)
else:
raise IncompleteCredentials(
"Connection requires email and password or access and refresh token."
"Missing oauth authentication details: email and password."
)

async def get(self, command):
Expand All @@ -90,6 +95,9 @@ async def post(self, command, method="post", data=None):
"""Post data to API."""
now = calendar.timegm(datetime.datetime.now().timetuple())
if now > self.expiration:
_LOGGER.debug(
"Requesting new oauth token using %s", self.oauth["grant_type"]
)
auth = await self.__open("/oauth/token", "post", data=self.oauth)
self.__sethead(auth["access_token"], auth["expires_in"])
self.refresh_token = auth["refresh_token"]
Expand Down
Loading

0 comments on commit 948a6e1

Please sign in to comment.