From 0792e72f718bc2affed1cedfdb8512c45587facf Mon Sep 17 00:00:00 2001 From: Conrad Juhl Andersen Date: Mon, 24 Jun 2019 20:30:45 +0200 Subject: [PATCH] Add support for sensor state STATE_UNAVAILABLE (#24641) * Fixed integration with ESPhome, which caused an error if ESPhome did not update fast enough on startup * Set state to problem if sensor is unavailable * Fix line length. --- homeassistant/components/plant/__init__.py | 36 +++++++++++------ tests/components/plant/test_init.py | 46 +++++++++++++++++++++- 2 files changed, 69 insertions(+), 13 deletions(-) diff --git a/homeassistant/components/plant/__init__.py b/homeassistant/components/plant/__init__.py index 78f979892b1..c4abc916c3f 100644 --- a/homeassistant/components/plant/__init__.py +++ b/homeassistant/components/plant/__init__.py @@ -9,7 +9,7 @@ from homeassistant.components import group from homeassistant.components.recorder.util import execute, session_scope from homeassistant.const import ( ATTR_TEMPERATURE, ATTR_UNIT_OF_MEASUREMENT, CONF_SENSORS, STATE_OK, - STATE_PROBLEM, STATE_UNKNOWN, TEMP_CELSIUS) + STATE_PROBLEM, STATE_UNAVAILABLE, STATE_UNKNOWN, TEMP_CELSIUS) from homeassistant.core import callback from homeassistant.exceptions import HomeAssistantError import homeassistant.helpers.config_validation as cv @@ -190,15 +190,25 @@ class Plant(Entity): reading = self._sensormap[entity_id] if reading == READING_MOISTURE: - self._moisture = int(float(value)) + if value != STATE_UNAVAILABLE: + value = int(float(value)) + self._moisture = value elif reading == READING_BATTERY: - self._battery = int(float(value)) + if value != STATE_UNAVAILABLE: + value = int(float(value)) + self._battery = value elif reading == READING_TEMPERATURE: - self._temperature = float(value) + if value != STATE_UNAVAILABLE: + value = float(value) + self._temperature = value elif reading == READING_CONDUCTIVITY: - self._conductivity = int(float(value)) + if value != STATE_UNAVAILABLE: + value = int(float(value)) + self._conductivity = value elif reading == READING_BRIGHTNESS: - self._brightness = int(float(value)) + if value != STATE_UNAVAILABLE: + value = int(float(value)) + self._brightness = value self._brightness_history.add_measurement( self._brightness, new_state.last_updated) else: @@ -216,12 +226,16 @@ class Plant(Entity): params = self.READINGS[sensor_name] value = getattr(self, '_{}'.format(sensor_name)) if value is not None: - if sensor_name == READING_BRIGHTNESS: - result.append(self._check_min( - sensor_name, self._brightness_history.max, params)) + if value == STATE_UNAVAILABLE: + result.append('{} unavailable'.format(sensor_name)) else: - result.append(self._check_min(sensor_name, value, params)) - result.append(self._check_max(sensor_name, value, params)) + if sensor_name == READING_BRIGHTNESS: + result.append(self._check_min( + sensor_name, self._brightness_history.max, params)) + else: + result.append(self._check_min(sensor_name, value, + params)) + result.append(self._check_max(sensor_name, value, params)) result = [r for r in result if r is not None] diff --git a/tests/components/plant/test_init.py b/tests/components/plant/test_init.py index 13cfb310bcd..fb32abafbb0 100644 --- a/tests/components/plant/test_init.py +++ b/tests/components/plant/test_init.py @@ -4,8 +4,8 @@ import unittest import pytest from datetime import datetime, timedelta -from homeassistant.const import (ATTR_UNIT_OF_MEASUREMENT, STATE_UNKNOWN, - STATE_PROBLEM, STATE_OK) +from homeassistant.const import (ATTR_UNIT_OF_MEASUREMENT, STATE_UNAVAILABLE, + STATE_UNKNOWN, STATE_PROBLEM, STATE_OK) from homeassistant.components import recorder import homeassistant.components.plant as plant from homeassistant.setup import setup_component @@ -118,6 +118,48 @@ class TestPlant(unittest.TestCase): assert STATE_PROBLEM == state.state assert 5 == state.attributes[plant.READING_MOISTURE] + def test_unavailable_state(self): + """Test updating the state with unavailable. + + Make sure that plant processes this correctly. + """ + plant_name = 'some_plant' + assert setup_component(self.hass, plant.DOMAIN, { + plant.DOMAIN: { + plant_name: GOOD_CONFIG + } + }) + self.hass.states.set(MOISTURE_ENTITY, STATE_UNAVAILABLE, + {ATTR_UNIT_OF_MEASUREMENT: 'us/cm'}) + self.hass.block_till_done() + state = self.hass.states.get('plant.'+plant_name) + assert state.state == STATE_PROBLEM + assert state.attributes[plant.READING_MOISTURE] == STATE_UNAVAILABLE + + def test_state_problem_if_unavailable(self): + """Test updating the state with unavailable after setting it to valid value. + + Make sure that plant processes this correctly. + """ + plant_name = 'some_plant' + assert setup_component(self.hass, plant.DOMAIN, { + plant.DOMAIN: { + plant_name: GOOD_CONFIG + } + }) + self.hass.states.set(MOISTURE_ENTITY, 42, + {ATTR_UNIT_OF_MEASUREMENT: 'us/cm'}) + self.hass.block_till_done() + state = self.hass.states.get('plant.' + plant_name) + assert state.state == STATE_OK + assert state.attributes[plant.READING_MOISTURE] == 42 + self.hass.states.set(MOISTURE_ENTITY, STATE_UNAVAILABLE, + {ATTR_UNIT_OF_MEASUREMENT: 'us/cm'}) + self.hass.block_till_done() + state = self.hass.states.get('plant.'+plant_name) + assert state.state == STATE_PROBLEM + assert state.attributes[plant.READING_MOISTURE] == STATE_UNAVAILABLE + @pytest.mark.skipif(plant.ENABLE_LOAD_HISTORY is False, reason="tests for loading from DB are unstable, thus" "this feature is turned of until tests become"