From e1797ea6709e4489ce592aa04e89927e3a9b6cec Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 30 Jun 2021 00:33:04 +1200 Subject: [PATCH] Add number entities to ESPHome (#52241) Co-authored-by: Franck Nijhof --- .coveragerc | 1 + .../components/esphome/entry_data.py | 2 + .../components/esphome/manifest.json | 2 +- homeassistant/components/esphome/number.py | 85 +++++++++++++++++++ requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 6 files changed, 91 insertions(+), 3 deletions(-) create mode 100644 homeassistant/components/esphome/number.py diff --git a/.coveragerc b/.coveragerc index ade61c1fb07..6fb95b595cc 100644 --- a/.coveragerc +++ b/.coveragerc @@ -274,6 +274,7 @@ omit = homeassistant/components/esphome/entry_data.py homeassistant/components/esphome/fan.py homeassistant/components/esphome/light.py + homeassistant/components/esphome/number.py homeassistant/components/esphome/sensor.py homeassistant/components/esphome/switch.py homeassistant/components/essent/sensor.py diff --git a/homeassistant/components/esphome/entry_data.py b/homeassistant/components/esphome/entry_data.py index dc964d0eb2e..49655de8fb7 100644 --- a/homeassistant/components/esphome/entry_data.py +++ b/homeassistant/components/esphome/entry_data.py @@ -16,6 +16,7 @@ from aioesphomeapi import ( EntityState, FanInfo, LightInfo, + NumberInfo, SensorInfo, SwitchInfo, TextSensorInfo, @@ -41,6 +42,7 @@ INFO_TYPE_TO_PLATFORM = { CoverInfo: "cover", FanInfo: "fan", LightInfo: "light", + NumberInfo: "number", SensorInfo: "sensor", SwitchInfo: "switch", TextSensorInfo: "sensor", diff --git a/homeassistant/components/esphome/manifest.json b/homeassistant/components/esphome/manifest.json index 9182be8d496..284fdc25956 100644 --- a/homeassistant/components/esphome/manifest.json +++ b/homeassistant/components/esphome/manifest.json @@ -3,7 +3,7 @@ "name": "ESPHome", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/esphome", - "requirements": ["aioesphomeapi==3.0.1"], + "requirements": ["aioesphomeapi==3.1.0"], "zeroconf": ["_esphomelib._tcp.local."], "codeowners": ["@OttoWinter", "@jesserockz"], "after_dependencies": ["zeroconf", "tag"], diff --git a/homeassistant/components/esphome/number.py b/homeassistant/components/esphome/number.py new file mode 100644 index 00000000000..08b31e91b79 --- /dev/null +++ b/homeassistant/components/esphome/number.py @@ -0,0 +1,85 @@ +"""Support for esphome numbers.""" +from __future__ import annotations + +import math + +from aioesphomeapi import NumberInfo, NumberState +import voluptuous as vol + +from homeassistant.components.number import NumberEntity +from homeassistant.config_entries import ConfigEntry +from homeassistant.core import HomeAssistant +import homeassistant.helpers.config_validation as cv +from homeassistant.helpers.entity_platform import AddEntitiesCallback + +from . import EsphomeEntity, esphome_state_property, platform_async_setup_entry + +ICON_SCHEMA = vol.Schema(cv.icon) + + +async def async_setup_entry( + hass: HomeAssistant, + entry: ConfigEntry, + async_add_entities: AddEntitiesCallback, +) -> None: + """Set up esphome numbers based on a config entry.""" + await platform_async_setup_entry( + hass, + entry, + async_add_entities, + component_key="number", + info_type=NumberInfo, + entity_type=EsphomeNumber, + state_type=NumberState, + ) + + +# https://github.com/PyCQA/pylint/issues/3150 for all @esphome_state_property +# pylint: disable=invalid-overridden-method + + +class EsphomeNumber(EsphomeEntity, NumberEntity): + """A number implementation for esphome.""" + + @property + def _static_info(self) -> NumberInfo: + return super()._static_info + + @property + def _state(self) -> NumberState | None: + return super()._state + + @property + def icon(self) -> str | None: + """Return the icon.""" + if not self._static_info.icon: + return None + return ICON_SCHEMA(self._static_info.icon) + + @property + def min_value(self) -> float: + """Return the minimum value.""" + return super()._static_info.min_value + + @property + def max_value(self) -> float: + """Return the maximum value.""" + return super()._static_info.max_value + + @property + def step(self) -> float: + """Return the increment/decrement step.""" + return super()._static_info.step + + @esphome_state_property + def value(self) -> float: + """Return the state of the entity.""" + if math.isnan(self._state.state): + return None + if self._state.missing_state: + return None + return self._state.state + + async def async_set_value(self, value: float) -> None: + """Update the current value.""" + await self._client.number_command(self._static_info.key, value) diff --git a/requirements_all.txt b/requirements_all.txt index 3f6d3e5ccec..eb3e6115da7 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -160,7 +160,7 @@ aioeafm==0.1.2 aioemonitor==1.0.5 # homeassistant.components.esphome -aioesphomeapi==3.0.1 +aioesphomeapi==3.1.0 # homeassistant.components.flo aioflo==0.4.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 6dfec7520a5..4b019058c77 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -100,7 +100,7 @@ aioeafm==0.1.2 aioemonitor==1.0.5 # homeassistant.components.esphome -aioesphomeapi==3.0.1 +aioesphomeapi==3.1.0 # homeassistant.components.flo aioflo==0.4.1