-
Notifications
You must be signed in to change notification settings - Fork 100
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Support for Heated Steering Wheel and Seats #188
Changes from 6 commits
1c83a90
fd1db45
223e74f
7942e5a
4dd0668
f0d3552
8300989
7e23a21
e8dbc3d
1e9867d
c2324e7
4a4bba6
bfd8cb5
98313e0
c6124d2
f300afd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
"""Helpers module. | ||
|
||
A collection of functions which may be used accross entities | ||
""" | ||
from .const import DOMAIN as TESLA_DOMAIN | ||
|
||
import asyncio | ||
import async_timeout | ||
import logging | ||
|
||
from homeassistant.core import HomeAssistant | ||
|
||
_LOGGER = logging.getLogger(__name__) | ||
|
||
|
||
async def get_device( | ||
hass: HomeAssistant, | ||
config_entry_id: str, | ||
device_category: str, | ||
device_type: str, | ||
): | ||
"""Get a tesla Device for a Config Entry ID.""" | ||
|
||
entry_data = hass.data[TESLA_DOMAIN][config_entry_id] | ||
devices = entry_data["devices"].get(device_category, []) | ||
|
||
for device in devices: | ||
if device.type == device_type: | ||
return device | ||
|
||
return None | ||
|
||
|
||
async def wait_for_climate( | ||
hass: HomeAssistant, config_entry_id: str, timeout: int = 30 | ||
): | ||
"""Wait for HVac. | ||
|
||
Optional Timeout. defaults to 30 seconds | ||
""" | ||
climate_device = await get_device( | ||
hass, config_entry_id, "climate", "HVAC (climate) system" | ||
) | ||
|
||
if climate_device is None: | ||
return None | ||
|
||
async with async_timeout.timeout(timeout): | ||
while True: | ||
hvac_mode = climate_device.is_hvac_enabled() | ||
|
||
if hvac_mode is True: | ||
_LOGGER.debug("HVAC Enabled") | ||
return True | ||
else: | ||
_LOGGER.info("Enabing Climate to activate Heated Steering Wheel") | ||
|
||
# The below is a blocking funtion (it waits for a reponse from the API). | ||
# So it could eat into our timeout, and this is fine. | ||
# We'll try to turn the set the status, and check again | ||
try: | ||
await climate_device.set_status(True) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How often on your system does this hit the Tesla endpoint? The issue I'm concerned about is that each api call has a wake call which includes 5 separate retries. Since this loop in theory can hit 15 times and if there's a wakeup that quickly goes to 75 api hits. Are we slamming the endpoint unnecessarily? |
||
continue | ||
except: | ||
# If we get an error, we'll just loop around and try again | ||
pass | ||
|
||
# Wait two second between API calls, in case we get an error like car unavail, | ||
# or any other random thing tesla throws at us | ||
await asyncio.sleep(2) | ||
|
||
# we'll return false if the timeout is reached. | ||
return False |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
"""Support for Tesla selects.""" | ||
import logging | ||
|
||
from homeassistant.components.select import SelectEntity | ||
|
||
from . import DOMAIN as TESLA_DOMAIN | ||
from .tesla_device import TeslaDevice | ||
from .helpers import wait_for_climate | ||
|
||
_LOGGER = logging.getLogger(__name__) | ||
|
||
OPTIONS = [ | ||
"Off", | ||
"Low", | ||
"Medium", | ||
"High", | ||
] | ||
|
||
|
||
async def async_setup_entry(hass, config_entry, async_add_entities): | ||
"""Set up the Tesla selects by config_entry.""" | ||
coordinator = hass.data[TESLA_DOMAIN][config_entry.entry_id]["coordinator"] | ||
entities = [] | ||
for device in hass.data[TESLA_DOMAIN][config_entry.entry_id]["devices"]["select"]: | ||
if device.type.startswith("heated seat "): | ||
entities.append(HeatedSeatSelect(device, coordinator)) | ||
async_add_entities(entities, True) | ||
|
||
|
||
class HeatedSeatSelect(TeslaDevice, SelectEntity): | ||
"""Representation of a Tesla Heated Seat Select.""" | ||
|
||
async def async_select_option(self, option: str, **kwargs): | ||
"""Change the selected option.""" | ||
level: int = OPTIONS.index(option) | ||
|
||
await wait_for_climate(self.hass, self.config_entry_id) | ||
_LOGGER.debug("Setting %s to %s", self.name, level) | ||
await self.tesla_device.set_seat_heat_level(level) | ||
self.async_write_ha_state() | ||
|
||
@property | ||
def current_option(self): | ||
"""Return the selected entity option to represent the entity state.""" | ||
current_value = self.tesla_device.get_seat_heat_level() | ||
|
||
if current_value is None: | ||
return OPTIONS[0] | ||
return OPTIONS[current_value] | ||
|
||
@property | ||
def options(self): | ||
"""Return a set of selectable options.""" | ||
return OPTIONS |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By adding a public method to allow resetting the manual update time?
Perhaps it's worth filing an issue on the
teslajsonpy
repo, so this doesn't get forgotten.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, let's open an issue. Basically what you're saying we need is a way to force a device to reread its info from cache.
I'm ok with the current approach for a 1.0 type release, but it makes sense to resolve it more cleanly in the future.