From 38d644f9d7cbc7ccfe94d5e7b2ce53ab917de073 Mon Sep 17 00:00:00 2001 From: Raph Date: Sun, 5 Dec 2021 23:54:39 +0100 Subject: [PATCH] feat: add Horn & FlashLight buttons (#252) Co-authored-by: raphael --- teslajsonpy/__init__.py | 3 + teslajsonpy/connection.py | 4 +- teslajsonpy/controller.py | 3 + teslajsonpy/homeassistant/alerts.py | 99 +++++++++++++++++++ teslajsonpy/homeassistant/charger.py | 8 +- tests/unit_tests/homeassistant/test_alerts.py | 46 +++++++++ 6 files changed, 158 insertions(+), 5 deletions(-) create mode 100644 teslajsonpy/homeassistant/alerts.py create mode 100644 tests/unit_tests/homeassistant/test_alerts.py diff --git a/teslajsonpy/__init__.py b/teslajsonpy/__init__.py index 4e7b4908..9cca61a3 100644 --- a/teslajsonpy/__init__.py +++ b/teslajsonpy/__init__.py @@ -26,6 +26,7 @@ from teslajsonpy.homeassistant.lock import Lock from teslajsonpy.homeassistant.sentry_mode import SentryModeSwitch from teslajsonpy.homeassistant.trunk import FrunkLock, TrunkLock +from teslajsonpy.homeassistant.alerts import Horn, FlashLights from teslajsonpy.teslaproxy import TeslaProxy from .__version__ import __version__ @@ -51,6 +52,8 @@ "Odometer", "Lock", "SentryModeSwitch", + "Horn", + "FlashLights", "TrunkLock", "FrunkLock", "__version__", diff --git a/teslajsonpy/connection.py b/teslajsonpy/connection.py index 6b61285d..ebc180e2 100644 --- a/teslajsonpy/connection.py +++ b/teslajsonpy/connection.py @@ -164,9 +164,7 @@ async def post(self, command, method="post", data=None, url=""): _LOGGER.debug("Successfully refreshed oauth") if not url: url = f"{self.api}{command}" - return await self.__open( - url, method=method, headers=self.head, data=data - ) + return await self.__open(url, method=method, headers=self.head, data=data) def __sethead(self, access_token: Text, expires_in: int = 30, expiration: int = 0): """Set HTTP header.""" diff --git a/teslajsonpy/controller.py b/teslajsonpy/controller.py index 62eafa0f..fe4b4357 100644 --- a/teslajsonpy/controller.py +++ b/teslajsonpy/controller.py @@ -52,6 +52,7 @@ from teslajsonpy.homeassistant.trunk import FrunkLock, TrunkLock from teslajsonpy.homeassistant.heated_steering_wheel import HeatedSteeringWheelSwitch from teslajsonpy.homeassistant.power import PowerSensor +from teslajsonpy.homeassistant.alerts import Horn, FlashLights _LOGGER = logging.getLogger(__name__) @@ -668,6 +669,8 @@ def _add_car_components(self, car): self.__components.append(FrunkLock(car, self)) self.__components.append(UpdateSensor(car, self)) self.__components.append(HeatedSteeringWheelSwitch(car, self)) + self.__components.append(Horn(car, self)) + self.__components.append(FlashLights(car, self)) for seat in ["left", "right", "rear_left", "rear_center", "rear_right"]: try: self.__components.append(HeatedSeatSelect(car, self, seat)) diff --git a/teslajsonpy/homeassistant/alerts.py b/teslajsonpy/homeassistant/alerts.py new file mode 100644 index 00000000..afe8b254 --- /dev/null +++ b/teslajsonpy/homeassistant/alerts.py @@ -0,0 +1,99 @@ +# 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 +""" + +from teslajsonpy.homeassistant.vehicle import VehicleDevice + + +class Horn(VehicleDevice): + """Home-Assistant class for horn of Tesla vehicles.""" + + def __init__(self, data, controller): + """Initialize the horn for the vehicle. + + Parameters + ---------- + data : dict + The horn for a Tesla vehicle. + https://tesla-api.timdorr.com/vehicle/commands/alerts + controller : teslajsonpy.Controller + The controller that controls updates to the Tesla API. + + Returns + ------- + None + + """ + super().__init__(data, controller) + self.type = "horn" + self.hass_type = "button" + self.name = self._name() + self.uniq_name = self._uniq_name() + + async def async_update(self, wake_if_asleep=False, force=False): + """Update the horn of the vehicle.""" + await super().async_update(wake_if_asleep=wake_if_asleep) + self.refresh() + + @staticmethod + def has_battery() -> bool: + """Return whether the device has a battery.""" + return False + + async def honk_horn(self) -> None: + """Horn.""" + await self._controller.api( + "HONK_HORN", + path_vars={"vehicle_id": self._id}, + on=True, + wake_if_asleep=True, + ) + + +class FlashLights(VehicleDevice): + """Home-Assistant class for flash lights of Tesla vehicles.""" + + def __init__(self, data, controller): + """Initialize the flash lights for the vehicle. + + Parameters + ---------- + data : dict + The flash lights for a Tesla vehicle. + https://tesla-api.timdorr.com/vehicle/commands/alerts + controller : teslajsonpy.Controller + The controller that controls updates to the Tesla API. + + Returns + ------- + None + + """ + super().__init__(data, controller) + self.type = "flash lights" + self.hass_type = "button" + self.name = self._name() + self.uniq_name = self._uniq_name() + + async def async_update(self, wake_if_asleep=False, force=False): + """Update the flash lights of the vehicle.""" + await super().async_update(wake_if_asleep=wake_if_asleep) + self.refresh() + + @staticmethod + def has_battery() -> bool: + """Return whether the device has a battery.""" + return False + + async def flash_lights(self) -> None: + """Flash Lights.""" + await self._controller.api( + "FLASH_LIGHTS", + path_vars={"vehicle_id": self._id}, + on=True, + wake_if_asleep=True, + ) diff --git a/teslajsonpy/homeassistant/charger.py b/teslajsonpy/homeassistant/charger.py index a92fda05..1cbfcb54 100644 --- a/teslajsonpy/homeassistant/charger.py +++ b/teslajsonpy/homeassistant/charger.py @@ -124,7 +124,9 @@ async def set_max(self): """Set the charger to max range for trips.""" if not self.__maxrange_state: data = await self._controller.api( - "CHANGE_CHARGE_MAX", path_vars={"vehicle_id": self._id}, wake_if_asleep=True + "CHANGE_CHARGE_MAX", + path_vars={"vehicle_id": self._id}, + wake_if_asleep=True, ) if data and data["response"]["result"]: self.__maxrange_state = True @@ -134,7 +136,9 @@ async def set_standard(self): """Set the charger to standard range for daily commute.""" if self.__maxrange_state: data = await self._controller.api( - "CHANGE_CHARGE_STANDARD", path_vars={"vehicle_id": self._id}, wake_if_asleep=True + "CHANGE_CHARGE_STANDARD", + path_vars={"vehicle_id": self._id}, + wake_if_asleep=True, ) if data and data["response"]["result"]: self.__maxrange_state = False diff --git a/tests/unit_tests/homeassistant/test_alerts.py b/tests/unit_tests/homeassistant/test_alerts.py new file mode 100644 index 00000000..c3bb11cd --- /dev/null +++ b/tests/unit_tests/homeassistant/test_alerts.py @@ -0,0 +1,46 @@ +"""Test sentry mode switch.""" + +import pytest + +from teslajsonpy.controller import Controller +from teslajsonpy.homeassistant.alerts import Horn, FlashLights + +from tests.tesla_mock import TeslaMock + + +def test_has_battery(monkeypatch): + """Test has_battery().""" + + _mock = TeslaMock(monkeypatch) + _controller = Controller(None) + + _data = _mock.data_request_vehicle() + _button = Horn(_data, _controller) + + assert not _button.has_battery() + + +@pytest.mark.asyncio +async def test_honk_horn(monkeypatch): + """Test test_honk_horn().""" + + _mock = TeslaMock(monkeypatch) + _controller = Controller(None) + + _data = _mock.data_request_vehicle() + _button = Horn(_data, _controller) + + await _button.honk_horn() + + +@pytest.mark.asyncio +async def test_flash_light(monkeypatch): + """Test test_flash_light().""" + + _mock = TeslaMock(monkeypatch) + _controller = Controller(None) + + _data = _mock.data_request_vehicle() + _button = FlashLights(_data, _controller) + + await _button.flash_lights()