From 4fdc4e28f103a88f6cc53a5c727f48c894192f0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Nenz=C3=A9n?= Date: Tue, 26 Jan 2021 01:47:28 +0100 Subject: [PATCH] Fixes sensor state not updating using coordinator (#12) --- custom_components/plaato/__init__.py | 39 ++++---- custom_components/plaato/binary_sensor.py | 7 +- custom_components/plaato/config_flow.py | 19 ++-- custom_components/plaato/const.py | 3 +- custom_components/plaato/entity.py | 2 +- custom_components/plaato/sensor.py | 18 ++-- custom_components/plaato/strings.json | 9 +- custom_components/plaato/translations/en.json | 99 +++++++++---------- 8 files changed, 96 insertions(+), 100 deletions(-) diff --git a/custom_components/plaato/__init__.py b/custom_components/plaato/__init__.py index 202bf1d..bf33d38 100644 --- a/custom_components/plaato/__init__.py +++ b/custom_components/plaato/__init__.py @@ -27,13 +27,14 @@ from homeassistant.components.sensor import DOMAIN as SENSOR from homeassistant.config_entries import ConfigEntry from homeassistant.const import ( + CONF_SCAN_INTERVAL, CONF_TOKEN, CONF_WEBHOOK_ID, HTTP_OK, TEMP_CELSIUS, TEMP_FAHRENHEIT, VOLUME_GALLONS, - VOLUME_LITERS, CONF_SCAN_INTERVAL, + VOLUME_LITERS, ) from homeassistant.core import HomeAssistant from homeassistant.exceptions import ConfigEntryNotReady, InvalidStateError @@ -47,6 +48,7 @@ CONF_DEVICE_TYPE, CONF_USE_WEBHOOK, COORDINATOR, + DEFAULT_SCAN_INTERVAL, DEVICE, DEVICE_ID, DEVICE_NAME, @@ -54,7 +56,7 @@ DOMAIN, PLATFORMS, SENSOR_DATA, - UNDO_UPDATE_LISTENER, DEFAULT_SCAN_INTERVAL, + UNDO_UPDATE_LISTENER, ) _LOGGER = logging.getLogger(__name__) @@ -129,8 +131,7 @@ async def async_setup_coordinator(hass: HomeAssistant, entry: ConfigEntry): device_type = entry.data[CONF_DEVICE_TYPE] if entry.options.get(CONF_SCAN_INTERVAL): - update_interval = timedelta( - minutes=entry.options[CONF_SCAN_INTERVAL]) + update_interval = timedelta(minutes=entry.options[CONF_SCAN_INTERVAL]) else: update_interval = DEFAULT_SCAN_INTERVAL @@ -176,30 +177,22 @@ async def async_unload_webhook(hass: HomeAssistant, entry: ConfigEntry): """Unload webhook based entry.""" if entry.data[CONF_WEBHOOK_ID] is not None: hass.components.webhook.async_unregister(entry.data[CONF_WEBHOOK_ID]) - - unloaded = all( - await asyncio.gather( - *[ - hass.config_entries.async_forward_entry_unload(entry, platform) - for platform in PLATFORMS - ] - ) - ) - if unloaded: - hass.data[DOMAIN].pop(entry.entry_id) - - return unloaded + return await async_unload_platforms(hass, entry, PLATFORMS) async def async_unload_coordinator(hass: HomeAssistant, entry: ConfigEntry): """Unload auth token based entry.""" coordinator = hass.data[DOMAIN][entry.entry_id][COORDINATOR] + return await async_unload_platforms(hass, entry, coordinator.platforms) + + +async def async_unload_platforms(hass: HomeAssistant, entry: ConfigEntry, platforms): + """Unload platforms.""" unloaded = all( await asyncio.gather( *[ hass.config_entries.async_forward_entry_unload(entry, platform) - for platform in PLATFORMS - if platform in coordinator.platforms + for platform in platforms ] ) ) @@ -238,7 +231,13 @@ def _device_id(data): class PlaatoCoordinator(DataUpdateCoordinator): """Class to manage fetching data from the API.""" - def __init__(self, hass, auth_token, device_type: PlaatoDeviceType, update_interval: timedelta): + def __init__( + self, + hass, + auth_token, + device_type: PlaatoDeviceType, + update_interval: timedelta, + ): """Initialize.""" self.api = Plaato(auth_token=auth_token) self.hass = hass diff --git a/custom_components/plaato/binary_sensor.py b/custom_components/plaato/binary_sensor.py index 136d10b..5b9ccdd 100644 --- a/custom_components/plaato/binary_sensor.py +++ b/custom_components/plaato/binary_sensor.py @@ -16,17 +16,14 @@ _LOGGER = logging.getLogger(__name__) -async def async_setup_entry(hass, config_entry, async_add_devices): +async def async_setup_entry(hass, config_entry, async_add_entities): """Set up Plaato from a config entry.""" if config_entry.data.get(CONF_USE_WEBHOOK, False): return False coordinator = hass.data[DOMAIN][config_entry.entry_id][COORDINATOR] - if coordinator.data is None: - return False - - async_add_devices( + async_add_entities( PlaatoBinarySensor( hass.data[DOMAIN][config_entry.entry_id], sensor_type, diff --git a/custom_components/plaato/config_flow.py b/custom_components/plaato/config_flow.py index 838ae6f..f36393f 100644 --- a/custom_components/plaato/config_flow.py +++ b/custom_components/plaato/config_flow.py @@ -15,11 +15,12 @@ CONF_DEVICE_NAME, CONF_DEVICE_TYPE, CONF_USE_WEBHOOK, + DEFAULT_SCAN_INTERVAL, DOCS_URL, PLACEHOLDER_DEVICE_NAME, PLACEHOLDER_DEVICE_TYPE, PLACEHOLDER_DOCS_URL, - PLACEHOLDER_WEBHOOK_URL, DEFAULT_SCAN_INTERVAL, + PLACEHOLDER_WEBHOOK_URL, ) from .const import DOMAIN # pylint:disable=unused-import @@ -104,9 +105,9 @@ async def async_step_webhook(self, user_input=None): }, ) - return await self._async_step_create_entry() + return await self._async_create_entry() - async def _async_step_create_entry(self): + async def _async_create_entry(self): """Create the entry step.""" webhook_id = self._init_info.get(CONF_WEBHOOK_ID, None) @@ -159,11 +160,9 @@ async def _get_webhook_id(self): @staticmethod def _get_error(device_type: PlaatoDeviceType): - return ( - "no_api_method" - if device_type == PlaatoDeviceType.Airlock - else "no_auth_token" - ) + if device_type == PlaatoDeviceType.Airlock: + return "no_api_method" + return "no_auth_token" @staticmethod @callback @@ -200,7 +199,9 @@ async def async_step_user(self, user_input=None): { vol.Optional( CONF_SCAN_INTERVAL, - default=self._config_entry.options.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL), + default=self._config_entry.options.get( + CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL + ), ): cv.positive_int } ), diff --git a/custom_components/plaato/const.py b/custom_components/plaato/const.py index b2a83ff..44d1613 100644 --- a/custom_components/plaato/const.py +++ b/custom_components/plaato/const.py @@ -1,4 +1,4 @@ -"""Const for GPSLogger.""" +"""Const for Plaato.""" from datetime import timedelta DOMAIN = "plaato" @@ -23,3 +23,4 @@ DEVICE_ID = "device_id" UNDO_UPDATE_LISTENER = "undo_update_listener" DEFAULT_SCAN_INTERVAL = timedelta(minutes=5) +MIN_UPDATE_INTERVAL = timedelta(minutes=1) diff --git a/custom_components/plaato/entity.py b/custom_components/plaato/entity.py index 1d09eb8..97f14cb 100644 --- a/custom_components/plaato/entity.py +++ b/custom_components/plaato/entity.py @@ -25,7 +25,7 @@ def __init__(self, data, sensor_type, coordinator=None): @property def name(self): """Return the name of the sensor.""" - return f"{self._name}".title() + return f"{DOMAIN} {self._device_type} {self._device_name} {self._name}".title() @property def unique_id(self): diff --git a/custom_components/plaato/sensor.py b/custom_components/plaato/sensor.py index 5416876..a13ca29 100644 --- a/custom_components/plaato/sensor.py +++ b/custom_components/plaato/sensor.py @@ -23,7 +23,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= """Set up the Plaato sensor.""" -async def async_setup_entry(hass, entry, async_add_devices): +async def async_setup_entry(hass, entry, async_add_entities): """Set up Plaato from a config entry.""" devices = {} @@ -40,7 +40,7 @@ async def _update_sensor(device_id, sensor_data: PlaatoDevice): for sensor_type in sensor_data.sensors.keys() ] devices[entry.entry_id] = entities - async_add_devices(entities) + async_add_entities(entities) else: for entity in devices[entry.entry_id]: async_dispatcher_send(hass, f"{DOMAIN}_{entity.unique_id}") @@ -49,13 +49,10 @@ async def _update_sensor(device_id, sensor_data: PlaatoDevice): async_dispatcher_connect(hass, SENSOR_UPDATE, _update_sensor) else: coordinator = hass.data[DOMAIN][entry.entry_id][COORDINATOR] - if coordinator.data is not None: - async_add_devices( - PlaatoSensor( - hass.data[DOMAIN][entry.entry_id], sensor_type, coordinator - ) - for sensor_type in coordinator.data.sensors.keys() - ) + async_add_entities( + PlaatoSensor(hass.data[DOMAIN][entry.entry_id], sensor_type, coordinator) + for sensor_type in coordinator.data.sensors.keys() + ) return True @@ -76,6 +73,9 @@ def device_class(self) -> Optional[str]: @property def state(self): """Return the state of the sensor.""" + if self._coordinator is not None: + return self._coordinator.data.sensors.get(self._sensor_type) + return self._sensor_data.sensors.get(self._sensor_type) @property diff --git a/custom_components/plaato/strings.json b/custom_components/plaato/strings.json index a5a97a0..852ecc8 100644 --- a/custom_components/plaato/strings.json +++ b/custom_components/plaato/strings.json @@ -1,10 +1,9 @@ { - "title": "Plaato", "config": { "step": { "user": { "title": "Set up the Plaato devices", - "description": "Select what devices you have", + "description": "[%key:common::config_flow::description::confirm_setup%]", "data": { "device_name": "Name your device", "device_type": "Type of Plaato device" @@ -29,9 +28,9 @@ "no_api_method": "You need to add an auth token or select webhook" }, "abort": { - "single_instance_allowed": "Already configured. Only a single configuration possible.", - "webhook_not_internet_accessible": "Your Home Assistant instance needs to be accessible from the internet to receive webhook messages.", - "already_configured": "Device is already configured" + "single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]", + "webhook_not_internet_accessible": "[%key:common::config_flow::abort::webhook_not_internet_accessible%]", + "already_configured": "[%key:common::config_flow::abort::already_configured_account%]" }, "create_entry": { "default": "Your Plaato {device_type} with name **{device_name}** was successfully setup!" diff --git a/custom_components/plaato/translations/en.json b/custom_components/plaato/translations/en.json index a5a97a0..64d41d0 100644 --- a/custom_components/plaato/translations/en.json +++ b/custom_components/plaato/translations/en.json @@ -1,55 +1,54 @@ { - "title": "Plaato", - "config": { - "step": { - "user": { - "title": "Set up the Plaato devices", - "description": "Select what devices you have", - "data": { - "device_name": "Name your device", - "device_type": "Type of Plaato device" + "config": { + "abort": { + "already_configured": "Account is already configured", + "single_instance_allowed": "Already configured. Only a single configuration possible.", + "webhook_not_internet_accessible": "Your Home Assistant instance needs to be accessible from the internet to receive webhook messages." + }, + "create_entry": { + "default": "Your Plaato {device_type} with name **{device_name}** was successfully setup!" + }, + "error": { + "invalid_webhook_device": "You have selected a device that doesn't not support sending data to a webhook. It is only available for the Airlock", + "no_api_method": "You need to add an auth token or select webhook", + "no_auth_token": "You need to add an auth token" + }, + "step": { + "api_method": { + "data": { + "token": "Paste Auth Token here", + "use_webhook": "Use webhook" + }, + "description": "To be able to query the API an `auth_token` is required which can be obtained by following [these](https://plaato.zendesk.com/hc/en-us/articles/360003234717-Auth-token) instructions\n\n Selected device: **{device_type}** \n\nIf you rather use the built in webhook method (Airlock only) please check the box below and leave Auth Token blank", + "title": "Select API method" + }, + "user": { + "data": { + "device_name": "Name your device", + "device_type": "Type of Plaato device" + }, + "description": "Do you want to start set up?", + "title": "Set up the Plaato devices" + }, + "webhook": { + "description": "To send events to Home Assistant, you will need to setup the webhook feature in Plaato Airlock.\n\nFill in the following info:\n\n- URL: `{webhook_url}`\n- Method: POST\n\nSee [the documentation]({docs_url}) for further details.", + "title": "Webhook to use" + } } - }, - "api_method": { - "title": "Select API method", - "description": "To be able to query the API an `auth_token` is required which can be obtained by following [these](https://plaato.zendesk.com/hc/en-us/articles/360003234717-Auth-token) instructions\n\n Selected device: **{device_type}** \n\nIf you rather use the built in webhook method (Airlock only) please check the box below and leave Auth Token blank", - "data": { - "use_webhook": "Use webhook", - "token": "Paste Auth Token here" - } - }, - "webhook": { - "title": "Webhook to use", - "description": "To send events to Home Assistant, you will need to setup the webhook feature in Plaato Airlock.\n\nFill in the following info:\n\n- URL: `{webhook_url}`\n- Method: POST\n\nSee [the documentation]({docs_url}) for further details." - } - }, - "error": { - "invalid_webhook_device": "You have selected a device that doesn't not support sending data to a webhook. It is only available for the Airlock", - "no_auth_token": "You need to add an auth token", - "no_api_method": "You need to add an auth token or select webhook" }, - "abort": { - "single_instance_allowed": "Already configured. Only a single configuration possible.", - "webhook_not_internet_accessible": "Your Home Assistant instance needs to be accessible from the internet to receive webhook messages.", - "already_configured": "Device is already configured" - }, - "create_entry": { - "default": "Your Plaato {device_type} with name **{device_name}** was successfully setup!" - } - }, - "options": { - "step": { - "webhook": { - "title": "Options for Plaato Airlock", - "description": "Webhook info:\n\n- URL: `{webhook_url}`\n- Method: POST\n\n" - }, - "user": { - "title": "Options for Plaato", - "description": "Set the update interval (minutes)", - "data": { - "update_interval": "Update interval (minutes)" + "options": { + "step": { + "user": { + "data": { + "update_interval": "Update interval (minutes)" + }, + "description": "Set the update interval (minutes)", + "title": "Options for Plaato" + }, + "webhook": { + "description": "Webhook info:\n\n- URL: `{webhook_url}`\n- Method: POST\n\n", + "title": "Options for Plaato Airlock" + } } - } } - } -} +} \ No newline at end of file