-
Notifications
You must be signed in to change notification settings - Fork 62
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #79 from zabuldon/dev
0.8.0
- Loading branch information
Showing
6 changed files
with
413 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
# SPDX-License-Identifier: Apache-2.0 | ||
""" | ||
Python Package for controlling Tesla API. | ||
For more details about this api, please refer to the documentation at | ||
https://github.com/zabuldon/teslajsonpy | ||
""" | ||
import time | ||
|
||
from typing import Text | ||
|
||
from teslajsonpy.vehicle import VehicleDevice | ||
|
||
|
||
class TrunkLock(VehicleDevice): | ||
"""Home-Assistant rear trunk lock for a Tesla VehicleDevice.""" | ||
|
||
def __init__(self, data, controller): | ||
"""Initialize the rear trunk lock. | ||
Args: | ||
data (Dict): The vehicle state for a Tesla vehicle. | ||
https://tesla-api.timdorr.com/vehicle/state/vehiclestate | ||
controller (Controller): The controller that controls updates to the Tesla API. | ||
""" | ||
super().__init__(data, controller) | ||
self.__lock_state: int = None | ||
self.type: Text = "trunk lock" | ||
self.hass_type: Text = "lock" | ||
self.sensor_type: Text = "door" | ||
self.bin_type = 0x7 | ||
self.name: Text = self._name() | ||
self.uniq_name: Text = self._uniq_name() | ||
self.__manual_update_time = 0 | ||
|
||
async def async_update(self, wake_if_asleep=False, force=False) -> None: | ||
"""Update the rear trunk state.""" | ||
await super().async_update(wake_if_asleep=wake_if_asleep, force=force) | ||
last_update = self._controller.get_last_update_time(self._id) | ||
if last_update >= self.__manual_update_time: | ||
data = self._controller.get_state_params(self._id) | ||
self.__lock_state = data["rt"] if (data and "rt" in data) else None | ||
|
||
def is_locked(self): | ||
"""Return whether the rear trunk is closed.""" | ||
return self.__lock_state == 0 | ||
|
||
async def unlock(self): | ||
"""Open the rear trunk.""" | ||
if self.is_locked(): | ||
data = await self._controller.command( | ||
self._id, "actuate_trunk", {"which_trunk": "rear"}, wake_if_asleep=True | ||
) | ||
if data and data["response"]["result"]: | ||
self.__lock_state = 255 | ||
self.__manual_update_time = time.time() | ||
|
||
async def lock(self): | ||
"""Close the rear trunk.""" | ||
if not self.is_locked(): | ||
data = await self._controller.command( | ||
self._id, "actuate_trunk", {"which_trunk": "rear"}, wake_if_asleep=True | ||
) | ||
if data and data["response"]["result"]: | ||
self.__lock_state = 0 | ||
self.__manual_update_time = time.time() | ||
|
||
@staticmethod | ||
def has_battery(): | ||
"""Return whether the device has a battery.""" | ||
return False | ||
|
||
|
||
class FrunkLock(VehicleDevice): | ||
"""Home-Assistant front trunk (frunk) lock for a Tesla VehicleDevice.""" | ||
|
||
def __init__(self, data, controller): | ||
"""Initialize the front trunk (frunk) lock. | ||
Args: | ||
data (Dict): The vehicle state for a Tesla vehicle. | ||
https://tesla-api.timdorr.com/vehicle/state/vehiclestate | ||
controller (Controller): The controller that controls updates to the Tesla API. | ||
""" | ||
super().__init__(data, controller) | ||
self.__lock_state: int = None | ||
self.type: Text = "frunk lock" | ||
self.hass_type: Text = "lock" | ||
self.sensor_type: Text = "door" | ||
self.bin_type = 0x7 | ||
self.name: Text = self._name() | ||
self.uniq_name: Text = self._uniq_name() | ||
self.__manual_update_time = 0 | ||
|
||
async def async_update(self, wake_if_asleep=False, force=False) -> None: | ||
"""Update the front trunk (frunk) state.""" | ||
await super().async_update(wake_if_asleep=wake_if_asleep, force=force) | ||
last_update = self._controller.get_last_update_time(self._id) | ||
if last_update >= self.__manual_update_time: | ||
data = self._controller.get_state_params(self._id) | ||
self.__lock_state = data["ft"] if (data and "ft" in data) else None | ||
|
||
def is_locked(self): | ||
"""Return whether the front trunk (frunk) is closed.""" | ||
return self.__lock_state == 0 | ||
|
||
async def unlock(self): | ||
"""Open the front trunk (frunk).""" | ||
if self.is_locked(): | ||
data = await self._controller.command( | ||
self._id, "actuate_trunk", {"which_trunk": "front"}, wake_if_asleep=True | ||
) | ||
if data and data["response"]["result"]: | ||
self.__lock_state = 255 | ||
self.__manual_update_time = time.time() | ||
|
||
async def lock(self): | ||
"""Close the front trunk (frunk).""" | ||
if not self.is_locked(): | ||
data = await self._controller.command( | ||
self._id, "actuate_trunk", {"which_trunk": "front"}, wake_if_asleep=True | ||
) | ||
if data and data["response"]["result"]: | ||
self.__lock_state = 0 | ||
self.__manual_update_time = time.time() | ||
|
||
@staticmethod | ||
def has_battery(): | ||
"""Return whether the device has a battery.""" | ||
return False |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
"""Test frunk lock.""" | ||
|
||
import pytest | ||
|
||
from tests.tesla_mock import TeslaMock | ||
|
||
from teslajsonpy.controller import Controller | ||
from teslajsonpy.trunk import FrunkLock | ||
|
||
|
||
def test_has_battery(monkeypatch): | ||
"""Test has_battery().""" | ||
|
||
_mock = TeslaMock(monkeypatch) | ||
_controller = Controller(None) | ||
|
||
_data = _mock.data_request_vehicle() | ||
_lock = FrunkLock(_data, _controller) | ||
|
||
assert not _lock.has_battery() | ||
|
||
|
||
def test_is_locked_on_init(monkeypatch): | ||
"""Test is_locked() after initialization.""" | ||
|
||
_mock = TeslaMock(monkeypatch) | ||
_controller = Controller(None) | ||
|
||
_data = _mock.data_request_vehicle() | ||
_lock = FrunkLock(_data, _controller) | ||
|
||
assert _lock is not None | ||
assert not _lock.is_locked() | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_is_locked_after_update(monkeypatch): | ||
"""Test is_locked() after an update.""" | ||
|
||
_mock = TeslaMock(monkeypatch) | ||
_controller = Controller(None) | ||
|
||
_data = _mock.data_request_vehicle() | ||
_data["vehicle_state"]["ft"] = 0 | ||
_lock = FrunkLock(_data, _controller) | ||
|
||
await _lock.async_update() | ||
|
||
assert _lock is not None | ||
assert _lock.is_locked() | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_unlock(monkeypatch): | ||
"""Test unlock().""" | ||
|
||
_mock = TeslaMock(monkeypatch) | ||
_controller = Controller(None) | ||
|
||
_data = _mock.data_request_vehicle() | ||
_data["vehicle_state"]["ft"] = 0 | ||
_lock = FrunkLock(_data, _controller) | ||
|
||
await _lock.async_update() | ||
await _lock.unlock() | ||
|
||
assert _lock is not None | ||
assert not _lock.is_locked() | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_unlock_already_unlocked(monkeypatch): | ||
"""Test unlock() when already unlocked.""" | ||
|
||
_mock = TeslaMock(monkeypatch) | ||
_controller = Controller(None) | ||
|
||
_data = _mock.data_request_vehicle() | ||
_data["vehicle_state"]["ft"] = 123 | ||
_lock = FrunkLock(_data, _controller) | ||
|
||
await _lock.async_update() | ||
await _lock.unlock() | ||
|
||
assert _lock is not None | ||
assert not _lock.is_locked() | ||
|
||
# Reset to default for next tests | ||
_data["vehicle_state"]["ft"] = 0 | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_lock(monkeypatch): | ||
"""Test lock().""" | ||
|
||
_mock = TeslaMock(monkeypatch) | ||
_controller = Controller(None) | ||
|
||
_data = _mock.data_request_vehicle() | ||
_data["vehicle_state"]["ft"] = 123 | ||
_lock = FrunkLock(_data, _controller) | ||
|
||
await _lock.async_update() | ||
await _lock.lock() | ||
|
||
assert _lock is not None | ||
assert _lock.is_locked() | ||
|
||
# Reset to default for next tests | ||
_data["vehicle_state"]["ft"] = 0 | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_lock_already_locked(monkeypatch): | ||
"""Test lock() when already locked.""" | ||
|
||
_mock = TeslaMock(monkeypatch) | ||
_controller = Controller(None) | ||
|
||
_data = _mock.data_request_vehicle() | ||
_data["vehicle_state"]["ft"] = 0 | ||
_lock = FrunkLock(_data, _controller) | ||
|
||
await _lock.async_update() | ||
await _lock.lock() | ||
|
||
assert _lock is not None | ||
assert _lock.is_locked() |
Oops, something went wrong.