From 3b2d8bc4be6ba6d00e15356f94eed4c2d4dde9e1 Mon Sep 17 00:00:00 2001 From: Olen Date: Sat, 15 Jan 2022 09:55:39 +0100 Subject: [PATCH] feat: add polling interval service (#128) --- custom_components/tesla_custom/__init__.py | 1 + custom_components/tesla_custom/const.py | 1 + custom_components/tesla_custom/services.py | 68 +++++++++++++++++++- custom_components/tesla_custom/services.yaml | 15 +++++ 4 files changed, 84 insertions(+), 1 deletion(-) diff --git a/custom_components/tesla_custom/__init__.py b/custom_components/tesla_custom/__init__.py index df1fb1fb..f869afd6 100644 --- a/custom_components/tesla_custom/__init__.py +++ b/custom_components/tesla_custom/__init__.py @@ -274,6 +274,7 @@ async def _async_update_data(self): # Note: asyncio.TimeoutError and aiohttp.ClientError are already # handled by the data update coordinator. async with async_timeout.timeout(30): + _LOGGER.debug("Running controller.update()") return await self.controller.update() except IncompleteCredentials: await self.hass.config_entries.async_reload(self.config_entry.entry_id) diff --git a/custom_components/tesla_custom/const.py b/custom_components/tesla_custom/const.py index ef702062..e770b02b 100644 --- a/custom_components/tesla_custom/const.py +++ b/custom_components/tesla_custom/const.py @@ -44,3 +44,4 @@ ATTR_PARAMETERS = "parameters" ATTR_PATH_VARS = "path_vars" SERVICE_API = "api" +SERVICE_SCAN_INTERVAL = "polling_interval" diff --git a/custom_components/tesla_custom/services.py b/custom_components/tesla_custom/services.py index b8488712..2f40da94 100644 --- a/custom_components/tesla_custom/services.py +++ b/custom_components/tesla_custom/services.py @@ -11,12 +11,17 @@ from homeassistant.helpers import config_validation as cv import voluptuous as vol -from homeassistant.const import ATTR_COMMAND +from homeassistant.const import ( + ATTR_COMMAND, + CONF_SCAN_INTERVAL, +) from .const import ( ATTR_PARAMETERS, ATTR_PATH_VARS, DOMAIN, SERVICE_API, + SERVICE_SCAN_INTERVAL, + DEFAULT_SCAN_INTERVAL, ) _LOGGER = logging.getLogger(__name__) @@ -30,6 +35,12 @@ } ) +SCAN_INTERVAL_SCHEMA = vol.Schema( + { + vol.Optional(CONF_EMAIL): vol.All(cv.string, vol.Length(min=1)), + vol.Required(CONF_SCAN_INTERVAL, default=DEFAULT_SCAN_INTERVAL): vol.All(vol.Coerce(int), vol.Range(min=0, max=3600)), + } +) @callback def async_setup_services(hass) -> None: @@ -42,6 +53,9 @@ async def async_call_tesla_service(service_call) -> None: if service == SERVICE_API: await api(service_call) + if service == SERVICE_SCAN_INTERVAL: + await set_update_interval(service_call) + hass.services.async_register( DOMAIN, SERVICE_API, @@ -49,6 +63,13 @@ async def async_call_tesla_service(service_call) -> None: schema=API_SCHEMA, ) + hass.services.async_register( + DOMAIN, + SERVICE_SCAN_INTERVAL, + async_call_tesla_service, + schema=SCAN_INTERVAL_SCHEMA, + ) + async def api(call): """Handle api service request. @@ -88,8 +109,53 @@ async def api(call): path_vars = parameters.pop(ATTR_PATH_VARS) return await controller.api(name=command, path_vars=path_vars, **parameters) + async def set_update_interval(call): + """Handle api service request. + + Arguments: + call.CONF_EMAIL {str: ""} -- email, optional + call.CONF_SCAN_INTERVAL {int: 660} -- New scan interval + + Returns: + bool -- True if new interval is set + + """ + _LOGGER.debug("call %s", call) + service_data = call.data + email = service_data.get(CONF_EMAIL, "") + + if len(hass.config_entries.async_entries(DOMAIN)) > 1 and not email: + raise ValueError("Email address missing") + controller: Controller = None + for entry in hass.config_entries.async_entries(DOMAIN): + if ( + len(hass.config_entries.async_entries(DOMAIN)) > 1 + and entry.title != email + ): + continue + controller = hass.data[DOMAIN].get(entry.entry_id)["coordinator"].controller + if controller is None: + raise ValueError(f"No Tesla controllers found for email {email}") + + update_interval = service_data.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL) + _LOGGER.debug( + "Service %s called with email: %s interval %s", + SERVICE_SCAN_INTERVAL, + email, + update_interval, + ) + old_update_interval = controller.update_interval + controller.update_interval = update_interval + if old_update_interval != controller.update_interval: + _LOGGER.debug( + "Changing update_interval from %s to %s", + old_update_interval, + controller.update_interval, + ) + return True @callback def async_unload_services(hass) -> None: """Unload Tesla services.""" hass.services.async_remove(DOMAIN, SERVICE_API) + hass.services.async_remove(DOMAIN, SERVICE_SCAN_INTERVAL) diff --git a/custom_components/tesla_custom/services.yaml b/custom_components/tesla_custom/services.yaml index cd7247c7..a0852c29 100644 --- a/custom_components/tesla_custom/services.yaml +++ b/custom_components/tesla_custom/services.yaml @@ -29,3 +29,18 @@ api: required: true selector: object: + +polling_interval: + description: Set polling interval for updating fresh data from an awake car + fields: + scan_interval: + description: Number of seconds between each poll. See https://github.com/alandtse/tesla/wiki/Polling-policy more information. + example: 660 + required: true + default: 660 + selector: + number: + min: 0 + max: 3600 + step: 30 + unit_of_measurement: "s"