-
Notifications
You must be signed in to change notification settings - Fork 61
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 #181 from zabuldon/dev
2021-04-01
- Loading branch information
Showing
4 changed files
with
195 additions
and
1 deletion.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
# 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 teslajsonpy.homeassistant.vehicle import VehicleDevice | ||
|
||
seat_id_map = { | ||
"left": 0, | ||
"right": 1, | ||
"rear_left": 2, | ||
"rear_center": 4, | ||
"rear_right": 5, | ||
} | ||
|
||
|
||
class HeatedSeatSwitch(VehicleDevice): | ||
"""Home-assistant heated seat class for Tesla vehicles. | ||
This is intended to be partially inherited by a Home-Assitant entity. | ||
""" | ||
|
||
def __init__(self, data, controller, seat_name): | ||
"""Initialize a heated seat for the vehicle. | ||
Parameters | ||
---------- | ||
data : dict | ||
The base state for a Tesla vehicle. | ||
https://tesla-api.timdorr.com/vehicle/state/data | ||
controller : teslajsonpy.Controller | ||
The controller that controls updates to the Tesla API. | ||
seat_name : string | ||
The name of the seat to control. | ||
One of "left", "right", "rear_left", "rear_center", "rear_right." | ||
Returns | ||
------- | ||
None | ||
""" | ||
super().__init__(data, controller) | ||
self.__manual_update_time = 0 | ||
self.__seat_heat_level = data['climate_state'][f'seat_heater_{seat_name}'] | ||
self.__seat_name = seat_name | ||
|
||
self.type = f"heated seat {seat_name}" | ||
self.hass_type = "switch" | ||
|
||
self.name = self._name() | ||
|
||
self.uniq_name = self._uniq_name() | ||
self.bin_type = 0x7 | ||
|
||
async def async_update(self, wake_if_asleep=False, force=False) -> None: | ||
"""Update the seat state.""" | ||
await super().async_update(wake_if_asleep=wake_if_asleep) | ||
self.refresh() | ||
|
||
def refresh(self) -> None: | ||
"""Refresh data. | ||
This assumes the controller has already been updated | ||
""" | ||
super().refresh() | ||
last_update = self._controller.get_last_update_time(self._id) | ||
if last_update >= self.__manual_update_time: | ||
data = self._controller.get_climate_params(self._id) | ||
self.__seat_heat_level = data[f'seat_heater_{self.__seat_name}'] if data else None | ||
|
||
async def set_seat_heat_level(self, level): | ||
"""Set heated seat level.""" | ||
data = await self._controller.command( | ||
self._id, "remote_seat_heater_request", data={ | ||
'heater': seat_id_map[self.__seat_name], | ||
'level': level | ||
}, wake_if_asleep=True | ||
) | ||
if data and data["response"]["result"]: | ||
self.__seat_heat_level = level | ||
self.__manual_update_time = time.time() | ||
|
||
def get_seat_heat_level(self): | ||
"""Return current heated seat level.""" | ||
return self.__seat_heat_level | ||
|
||
@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,95 @@ | ||
"""Test door HeatedSeatSwitch.""" | ||
|
||
import pytest | ||
|
||
from teslajsonpy.controller import Controller | ||
from teslajsonpy.homeassistant.heated_seats import HeatedSeatSwitch | ||
|
||
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() | ||
_seat = HeatedSeatSwitch(_data, _controller, 'left') | ||
|
||
assert not _seat.has_battery() | ||
|
||
|
||
def test_get_seat_heat_level_on_init(monkeypatch): | ||
"""Test get_seat_heat_level() after initialization.""" | ||
|
||
_mock = TeslaMock(monkeypatch) | ||
_controller = Controller(None) | ||
|
||
_data = _mock.data_request_vehicle() | ||
_seat = HeatedSeatSwitch(_data, _controller, 'left') | ||
|
||
assert not _seat is None | ||
assert _seat.get_seat_heat_level() == 3 # 3 is mocked initial level for left seat from tesla_mock.py | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_get_seat_heat_level_after_update(monkeypatch): | ||
"""Test get_seat_heat_level() after an update.""" | ||
|
||
_mock = TeslaMock(monkeypatch) | ||
_controller = Controller(None) | ||
|
||
NEW_LEVEL = 1 | ||
|
||
_data = _mock.data_request_vehicle() | ||
_data["climate_state"]['seat_heater_left'] = NEW_LEVEL | ||
_seat = HeatedSeatSwitch(_data, _controller, 'left') | ||
|
||
await _seat.async_update() | ||
|
||
assert not _seat is None | ||
assert _seat.get_seat_heat_level() == NEW_LEVEL | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_set_get_seat_heat_level(monkeypatch): | ||
"""Test HeatedSeatSwitch().""" | ||
|
||
_mock = TeslaMock(monkeypatch) | ||
_controller = Controller(None) | ||
|
||
ORIG_LEVEL = 1 | ||
NEW_LEVEL = 2 | ||
|
||
_data = _mock.data_request_vehicle() | ||
_data["climate_state"]["seat_heater_left"] = ORIG_LEVEL | ||
_seat = HeatedSeatSwitch(_data, _controller, 'left') | ||
|
||
await _seat.async_update() | ||
|
||
await _seat.set_seat_heat_level(NEW_LEVEL) | ||
|
||
assert not _seat is None | ||
assert _seat.get_seat_heat_level() == NEW_LEVEL | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_seat_same_level(monkeypatch): | ||
"""Test set_seat_heat_level to same level.""" | ||
|
||
_mock = TeslaMock(monkeypatch) | ||
_controller = Controller(None) | ||
|
||
ORIG_LEVEL = 1 | ||
|
||
_data = _mock.data_request_vehicle() | ||
_data["climate_state"]["seat_heater_left"] = ORIG_LEVEL | ||
_seat = HeatedSeatSwitch(_data, _controller, 'left') | ||
|
||
await _seat.async_update() | ||
|
||
await _seat.set_seat_heat_level(ORIG_LEVEL) | ||
|
||
assert not _seat is None | ||
assert _seat.get_seat_heat_level() == ORIG_LEVEL |