mirror of
https://github.com/home-assistant/core.git
synced 2025-11-08 02:19:31 +00:00
Add number platform support to Alexa (#86553)
Co-authored-by: Mike Degatano <michael.degatano@gmail.com>
This commit is contained in:
@@ -14,6 +14,7 @@ from homeassistant.components import (
|
||||
input_number,
|
||||
light,
|
||||
media_player,
|
||||
number,
|
||||
timer,
|
||||
vacuum,
|
||||
)
|
||||
@@ -26,6 +27,7 @@ from homeassistant.const import (
|
||||
ATTR_SUPPORTED_FEATURES,
|
||||
ATTR_TEMPERATURE,
|
||||
ATTR_UNIT_OF_MEASUREMENT,
|
||||
PERCENTAGE,
|
||||
STATE_ALARM_ARMED_AWAY,
|
||||
STATE_ALARM_ARMED_CUSTOM_BYPASS,
|
||||
STATE_ALARM_ARMED_HOME,
|
||||
@@ -41,6 +43,10 @@ from homeassistant.const import (
|
||||
STATE_UNKNOWN,
|
||||
STATE_UNLOCKED,
|
||||
STATE_UNLOCKING,
|
||||
UnitOfLength,
|
||||
UnitOfMass,
|
||||
UnitOfTemperature,
|
||||
UnitOfVolume,
|
||||
)
|
||||
from homeassistant.core import State
|
||||
import homeassistant.util.color as color_util
|
||||
@@ -65,6 +71,34 @@ from .resources import (
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
UNIT_TO_CATALOG_TAG = {
|
||||
UnitOfTemperature.CELSIUS: AlexaGlobalCatalog.UNIT_TEMPERATURE_CELSIUS,
|
||||
UnitOfTemperature.FAHRENHEIT: AlexaGlobalCatalog.UNIT_TEMPERATURE_FAHRENHEIT,
|
||||
UnitOfTemperature.KELVIN: AlexaGlobalCatalog.UNIT_TEMPERATURE_KELVIN,
|
||||
UnitOfLength.METERS: AlexaGlobalCatalog.UNIT_DISTANCE_METERS,
|
||||
UnitOfLength.KILOMETERS: AlexaGlobalCatalog.UNIT_DISTANCE_KILOMETERS,
|
||||
UnitOfLength.INCHES: AlexaGlobalCatalog.UNIT_DISTANCE_INCHES,
|
||||
UnitOfLength.FEET: AlexaGlobalCatalog.UNIT_DISTANCE_FEET,
|
||||
UnitOfLength.YARDS: AlexaGlobalCatalog.UNIT_DISTANCE_YARDS,
|
||||
UnitOfLength.MILES: AlexaGlobalCatalog.UNIT_DISTANCE_MILES,
|
||||
UnitOfMass.GRAMS: AlexaGlobalCatalog.UNIT_MASS_GRAMS,
|
||||
UnitOfMass.KILOGRAMS: AlexaGlobalCatalog.UNIT_MASS_KILOGRAMS,
|
||||
UnitOfMass.POUNDS: AlexaGlobalCatalog.UNIT_WEIGHT_POUNDS,
|
||||
UnitOfMass.OUNCES: AlexaGlobalCatalog.UNIT_WEIGHT_OUNCES,
|
||||
UnitOfVolume.LITERS: AlexaGlobalCatalog.UNIT_VOLUME_LITERS,
|
||||
UnitOfVolume.CUBIC_FEET: AlexaGlobalCatalog.UNIT_VOLUME_CUBIC_FEET,
|
||||
UnitOfVolume.CUBIC_METERS: AlexaGlobalCatalog.UNIT_VOLUME_CUBIC_METERS,
|
||||
UnitOfVolume.GALLONS: AlexaGlobalCatalog.UNIT_VOLUME_GALLONS,
|
||||
PERCENTAGE: AlexaGlobalCatalog.UNIT_PERCENT,
|
||||
"preset": AlexaGlobalCatalog.SETTING_PRESET,
|
||||
}
|
||||
|
||||
|
||||
def get_resource_by_unit_of_measurement(entity: State) -> str:
|
||||
"""Translate the unit of measurement to an Alexa Global Catalog keyword."""
|
||||
unit: str = entity.attributes.get("unit_of_measurement", "preset")
|
||||
return UNIT_TO_CATALOG_TAG.get(unit, AlexaGlobalCatalog.SETTING_PRESET)
|
||||
|
||||
|
||||
class AlexaCapability:
|
||||
"""Base class for Alexa capability interfaces.
|
||||
@@ -78,10 +112,16 @@ class AlexaCapability:
|
||||
|
||||
supported_locales = {"en-US"}
|
||||
|
||||
def __init__(self, entity: State, instance: str | None = None) -> None:
|
||||
def __init__(
|
||||
self,
|
||||
entity: State,
|
||||
instance: str | None = None,
|
||||
non_controllable_properties: bool | None = None,
|
||||
) -> None:
|
||||
"""Initialize an Alexa capability."""
|
||||
self.entity = entity
|
||||
self.instance = instance
|
||||
self._non_controllable_properties = non_controllable_properties
|
||||
|
||||
def name(self) -> str:
|
||||
"""Return the Alexa API name of this interface."""
|
||||
@@ -101,7 +141,7 @@ class AlexaCapability:
|
||||
|
||||
def properties_non_controllable(self) -> bool | None:
|
||||
"""Return True if non controllable."""
|
||||
return None
|
||||
return self._non_controllable_properties
|
||||
|
||||
def get_property(self, name):
|
||||
"""Read and return a property.
|
||||
@@ -1310,10 +1350,9 @@ class AlexaModeController(AlexaCapability):
|
||||
|
||||
def __init__(self, entity, instance, non_controllable=False):
|
||||
"""Initialize the entity."""
|
||||
super().__init__(entity, instance)
|
||||
AlexaCapability.__init__(self, entity, instance, non_controllable)
|
||||
self._resource = None
|
||||
self._semantics = None
|
||||
self.properties_non_controllable = lambda: non_controllable
|
||||
|
||||
def name(self):
|
||||
"""Return the Alexa API name of this interface."""
|
||||
@@ -1520,12 +1559,13 @@ class AlexaRangeController(AlexaCapability):
|
||||
"pt-BR",
|
||||
}
|
||||
|
||||
def __init__(self, entity, instance, non_controllable=False):
|
||||
def __init__(
|
||||
self, entity: State, instance: str | None, non_controllable: bool = False
|
||||
) -> None:
|
||||
"""Initialize the entity."""
|
||||
super().__init__(entity, instance)
|
||||
AlexaCapability.__init__(self, entity, instance, non_controllable)
|
||||
self._resource = None
|
||||
self._semantics = None
|
||||
self.properties_non_controllable = lambda: non_controllable
|
||||
|
||||
def name(self):
|
||||
"""Return the Alexa API name of this interface."""
|
||||
@@ -1579,6 +1619,10 @@ class AlexaRangeController(AlexaCapability):
|
||||
if self.instance == f"{input_number.DOMAIN}.{input_number.ATTR_VALUE}":
|
||||
return float(self.entity.state)
|
||||
|
||||
# Number Value
|
||||
if self.instance == f"{number.DOMAIN}.{number.ATTR_VALUE}":
|
||||
return float(self.entity.state)
|
||||
|
||||
# Vacuum Fan Speed
|
||||
if self.instance == f"{vacuum.DOMAIN}.{vacuum.ATTR_FAN_SPEED}":
|
||||
speed_list = self.entity.attributes.get(vacuum.ATTR_FAN_SPEED_LIST)
|
||||
@@ -1656,7 +1700,29 @@ class AlexaRangeController(AlexaCapability):
|
||||
unit = self.entity.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
|
||||
|
||||
self._resource = AlexaPresetResource(
|
||||
["Value", AlexaGlobalCatalog.SETTING_PRESET],
|
||||
["Value", get_resource_by_unit_of_measurement(self.entity)],
|
||||
min_value=min_value,
|
||||
max_value=max_value,
|
||||
precision=precision,
|
||||
unit=unit,
|
||||
)
|
||||
self._resource.add_preset(
|
||||
value=min_value, labels=[AlexaGlobalCatalog.VALUE_MINIMUM]
|
||||
)
|
||||
self._resource.add_preset(
|
||||
value=max_value, labels=[AlexaGlobalCatalog.VALUE_MAXIMUM]
|
||||
)
|
||||
return self._resource.serialize_capability_resources()
|
||||
|
||||
# Number Value
|
||||
if self.instance == f"{number.DOMAIN}.{number.ATTR_VALUE}":
|
||||
min_value = float(self.entity.attributes[number.ATTR_MIN])
|
||||
max_value = float(self.entity.attributes[number.ATTR_MAX])
|
||||
precision = float(self.entity.attributes.get(number.ATTR_STEP, 1))
|
||||
unit = self.entity.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
|
||||
|
||||
self._resource = AlexaPresetResource(
|
||||
["Value", get_resource_by_unit_of_measurement(self.entity)],
|
||||
min_value=min_value,
|
||||
max_value=max_value,
|
||||
precision=precision,
|
||||
@@ -1807,10 +1873,9 @@ class AlexaToggleController(AlexaCapability):
|
||||
|
||||
def __init__(self, entity, instance, non_controllable=False):
|
||||
"""Initialize the entity."""
|
||||
super().__init__(entity, instance)
|
||||
AlexaCapability.__init__(self, entity, instance, non_controllable)
|
||||
self._resource = None
|
||||
self._semantics = None
|
||||
self.properties_non_controllable = lambda: non_controllable
|
||||
|
||||
def name(self):
|
||||
"""Return the Alexa API name of this interface."""
|
||||
|
||||
Reference in New Issue
Block a user