Skip to content

Commit

Permalink
Merge pull request #46 from alandtse/config_entry
Browse files Browse the repository at this point in the history
feat: add support for HA config flow
  • Loading branch information
alandtse committed Oct 23, 2019
2 parents 673ecdb + e5d59a9 commit 46596cc
Show file tree
Hide file tree
Showing 13 changed files with 365 additions and 188 deletions.
1 change: 1 addition & 0 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ pylint = "*"
pytest-cov = "*"
tox = "*"
twine = "*"
python-semantic-release = "*"

[packages]
requests = "*"
464 changes: 293 additions & 171 deletions Pipfile.lock

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@ Python module for Tesla API primarily for enabling Home-Assistant.
working at any time without warning.

# Credits

Originally inspired by [this code.](https://github.com/gglockner/teslajson)
Also thanks to [Tim Dorr](https://tesla-api.timdorr.com/) for documenting the API. Additional repo scaffolding from [simplisafe-python.](https://github.com/bachya/simplisafe-python)

# Contributing

1. [Check for open features/bugs](https://github.com/zabuldon/teslajsonpy/issues)
or [initiate a discussion on one](https://github.com/zabuldon/teslajsonpy/issues/new).
or [initiate a discussion on one](https://github.com/zabuldon/teslajsonpy/issues/new).
2. [Fork the repository](https://github.com/zabuldon/teslajsonpy/fork/new).
3. Install the dev environment: `make init`.
4. Enter the virtual environment: `pipenv shell`
Expand All @@ -21,10 +22,11 @@ Also thanks to [Tim Dorr](https://tesla-api.timdorr.com/) for documenting the AP
7. Update `README.md` with any new documentation.
8. Run tests and ensure 100% code coverage for your contribution: `make coverage`
9. Ensure you have no linting errors: `make lint`
10. Ensure you have no typed your code correctly: `make typing`
10. Ensure you have typed your code correctly: `make typing`
11. Add yourself to `AUTHORS.md`.
12. Submit a [pull request](https://github.com/zabuldon/teslajsonpy/pulls)!

# License

[Apache-2.0](LICENSE). By providing a contribution, you agree the contribution is licensed under Apache-2.0.
This code is provided as-is with no warranty. Use at your own risk.
6 changes: 6 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[semantic_release]
version_variable=teslajsonpy/__version__.py:__version__
upload_to_pypi=false
check_build_status=false
remove_dist=false
hvcs=github
4 changes: 1 addition & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
URL = "https://github.com/zabuldon/teslajsonpy"
EMAIL = "sergey.isachenkol@bool.by"
AUTHOR = "Sergey Isachenko"
REQUIRES_PYTHON = ">=3.0"
REQUIRES_PYTHON = ">=3.6"
LICENSE = "Apache-2.0"
VERSION = None

Expand Down Expand Up @@ -132,8 +132,6 @@ def run(self):
'Intended Audience :: Developers',
'Operating System :: OS Independent',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Topic :: Internet',
Expand Down
2 changes: 2 additions & 0 deletions teslajsonpy/battery_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ def __init__(self, data, controller):
def update(self):
"""Update the battery state."""
self._controller.update(self._id, wake_if_asleep=False)
super().update()
data = self._controller.get_charging_params(self._id)
if data:
self.__battery_level = data['battery_level']
Expand Down Expand Up @@ -94,6 +95,7 @@ def __init__(self, data, controller):
def update(self):
"""Update the battery range state."""
self._controller.update(self._id, wake_if_asleep=False)
super().update()
data = self._controller.get_charging_params(self._id)
if data:
self.__battery_range = data['battery_range']
Expand Down
2 changes: 2 additions & 0 deletions teslajsonpy/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ def __init__(self, data, controller):
def update(self):
"""Update the parking brake sensor."""
self._controller.update(self._id, wake_if_asleep=False)
super().update()
data = self._controller.get_drive_params(self._id)
if data:
if not data['shift_state'] or data['shift_state'] == 'P':
Expand Down Expand Up @@ -101,6 +102,7 @@ def __init__(self, data, controller):
def update(self):
"""Update the charger connection sensor."""
self._controller.update(self._id, wake_if_asleep=False)
super().update()
data = self._controller.get_charging_params(self._id)
if data:
if data['charging_state'] in ["Disconnected"]:
Expand Down
2 changes: 2 additions & 0 deletions teslajsonpy/charger.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ def __init__(self, data, controller):
def update(self):
"""Update the charging state of the Tesla Vehicle."""
self._controller.update(self._id, wake_if_asleep=False)
super().update()
data = self._controller.get_charging_params(self._id)
if data and (time.time() - self.__manual_update_time > 60):
if data['charging_state'] != "Charging":
Expand Down Expand Up @@ -97,6 +98,7 @@ def __init__(self, data, controller):
def update(self):
"""Update the status of the range setting."""
self._controller.update(self._id, wake_if_asleep=False)
super().update()
data = self._controller.get_charging_params(self._id)
if data and (time.time() - self.__manual_update_time > 60):
self.__maxrange_state = data['charge_to_max_range']
Expand Down
3 changes: 2 additions & 1 deletion teslajsonpy/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def get_fan_status(self):
def update(self):
"""Update the HVAC state."""
self._controller.update(self._id, wake_if_asleep=False)

super().update()
data = self._controller.get_climate_params(self._id)
if data:
if time.time() - self.__manual_update_time > 60:
Expand Down Expand Up @@ -181,6 +181,7 @@ def get_outside_temp(self):
def update(self):
"""Update the temperature."""
self._controller.update(self._id, wake_if_asleep=False)
super().update()
data = self._controller.get_climate_params(self._id)
if data:
self.__inside_temp = (data['inside_temp'] if data['inside_temp']
Expand Down
29 changes: 18 additions & 11 deletions teslajsonpy/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ def __init__(self, email, password, update_interval):
self.__climate = {}
self.__charging = {}
self.__state = {}
self.__config = {}
self.__driving = {}
self.__gui = {}
self._last_update_time = {} # succesful attempts by car
Expand All @@ -69,14 +70,15 @@ def __init__(self, email, password, update_interval):
self._last_wake_up_time[car['id']] = 0
self.__update[car['id']] = True
self.car_online[car['id']] = (car['state'] == 'online')
self.__climate[car['id']] = False
self.__charging[car['id']] = False
self.__state[car['id']] = False
self.__driving[car['id']] = False
self.__gui[car['id']] = False
self.__climate[car['id']] = {}
self.__charging[car['id']] = {}
self.__state[car['id']] = {}
self.__config[car['id']] = {}
self.__driving[car['id']] = {}
self.__gui[car['id']] = {}

try:
self.update(car['id'], wake_if_asleep=False)
self.update(car['id'], wake_if_asleep=True)
except (TeslaException, RetryLimitError):
pass
self.__vehicles.append(Climate(car, self))
Expand Down Expand Up @@ -110,8 +112,10 @@ def wake_up(func):
should also be updated to allow that case
wake_if_asleep (bool): Keyword arg to force a vehicle awake. Must be
set in the wrapped function f
Throws:
RetryLimitError
"""
@wraps(func)
def wrapped(*args, **kwargs):
Expand Down Expand Up @@ -183,11 +187,9 @@ def valid_result(result):
time.sleep(sleep_delay**(retries+2))
retries += 1
continue
else:
inst.car_online[vehicle_id] = False
raise RetryLimitError
else:
break
inst.car_online[vehicle_id] = False
raise RetryLimitError
break
# try function five more times
retries = 0
while True:
Expand Down Expand Up @@ -404,6 +406,7 @@ def update(self, car_id=None, wake_if_asleep=False, force=False):
self.__climate[car_id] = response['climate_state']
self.__charging[car_id] = response['charge_state']
self.__state[car_id] = response['vehicle_state']
self.__config[car_id] = response['vehicle_config']
self.__driving[car_id] = response['drive_state']
self.__gui[car_id] = response['gui_settings']
self.car_online[car_id] = (response['state']
Expand All @@ -424,6 +427,10 @@ def get_state_params(self, car_id):
"""Return cached copy of state_params for car_id."""
return self.__state[car_id]

def get_config_params(self, car_id):
"""Return cached copy of state_params for car_id."""
return self.__config[car_id]

def get_drive_params(self, car_id):
"""Return cached copy of drive_params for car_id."""
return self.__driving[car_id]
Expand Down
2 changes: 2 additions & 0 deletions teslajsonpy/gps.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ def get_location(self):
def update(self):
"""Update the current GPS location."""
self._controller.update(self._id, wake_if_asleep=False)
super().update()
data = self._controller.get_drive_params(self._id)
if data:
self.__longitude = data['longitude']
Expand Down Expand Up @@ -102,6 +103,7 @@ def __init__(self, data, controller):
def update(self):
"""Update the odometer and the unit of measurement based on GUI."""
self._controller.update(self._id, wake_if_asleep=False)
super().update()
data = self._controller.get_state_params(self._id)
if data:
self.__odometer = data['odometer']
Expand Down
2 changes: 2 additions & 0 deletions teslajsonpy/lock.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ def __init__(self, data, controller):
def update(self):
"""Update the lock state."""
self._controller.update(self._id, wake_if_asleep=False)
super().update()
data = self._controller.get_state_params(self._id)
if data and (time.time() - self.__manual_update_time > 60):
self.__lock_state = data['locked']
Expand Down Expand Up @@ -120,6 +121,7 @@ def __init__(self, data, controller):
def update(self):
"""Update state of the charger lock."""
self._controller.update(self._id, wake_if_asleep=False)
super().update()
data = self._controller.get_charging_params(self._id)
if data and (time.time() - self.__manual_update_time > 60):
self.__lock_state = not ((data['charge_port_door_open']) and
Expand Down
30 changes: 30 additions & 0 deletions teslajsonpy/vehicle.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
For more details about this api, please refer to the documentation at
https://github.com/zabuldon/teslajsonpy
"""
import logging

_LOGGER = logging.getLogger(__name__)


class VehicleDevice:
Expand Down Expand Up @@ -36,6 +39,8 @@ def __init__(self, data, controller):
self._display_name = data['display_name']
self._vin = data['vin']
self._state = data['state']
self._car_type = f"Model {str(self._vin[3]).upper()}"
self._car_version = ""
self._controller = controller
self.should_poll = True
self.type = "device"
Expand All @@ -56,6 +61,25 @@ def id(self):
"""Return the id of this Vehicle."""
return self._id

def car_name(self):
"""Return the software version of this Vehicle."""
return (
self._display_name if
self._display_name is not None and
self._display_name != self._vin[-6:]
else f'Tesla Model {str(self._vin[3]).upper()}'
)

@property
def car_version(self):
"""Return the software version of this Vehicle."""
return self._car_version

@property
def car_type(self):
"""Return the type of this Vehicle."""
return self._car_type

def assumed_state(self):
# pylint: disable=protected-access
"""Return whether the data is from an online vehicle."""
Expand All @@ -64,6 +88,12 @@ def assumed_state(self):
self._controller._last_wake_up_time[self.id()] >
self._controller.update_interval))

def update(self):
"""Update the car version."""
state = self._controller.get_state_params(self.id())
if state and 'car_version' in state:
self._car_version = state['car_version']

@staticmethod
def is_armable():
"""Return whether the data is from an online vehicle."""
Expand Down

0 comments on commit 46596cc

Please sign in to comment.