100 lines
3.4 KiB
Python
100 lines
3.4 KiB
Python
"""Intents for the light integration."""
|
|
import voluptuous as vol
|
|
|
|
from homeassistant.const import ATTR_ENTITY_ID
|
|
from homeassistant.core import HomeAssistant, State
|
|
from homeassistant.helpers import intent
|
|
import homeassistant.helpers.config_validation as cv
|
|
import homeassistant.util.color as color_util
|
|
|
|
from . import (
|
|
ATTR_BRIGHTNESS_PCT,
|
|
ATTR_RGB_COLOR,
|
|
ATTR_SUPPORTED_COLOR_MODES,
|
|
DOMAIN,
|
|
SERVICE_TURN_ON,
|
|
brightness_supported,
|
|
color_supported,
|
|
)
|
|
|
|
INTENT_SET = "HassLightSet"
|
|
|
|
|
|
async def async_setup_intents(hass: HomeAssistant) -> None:
|
|
"""Set up the light intents."""
|
|
hass.helpers.intent.async_register(SetIntentHandler())
|
|
|
|
|
|
def _test_supports_color(state: State) -> None:
|
|
"""Test if state supports colors."""
|
|
supported_color_modes = state.attributes.get(ATTR_SUPPORTED_COLOR_MODES)
|
|
if not color_supported(supported_color_modes):
|
|
raise intent.IntentHandleError(
|
|
f"Entity {state.name} does not support changing colors"
|
|
)
|
|
|
|
|
|
def _test_supports_brightness(state: State) -> None:
|
|
"""Test if state supports brightness."""
|
|
supported_color_modes = state.attributes.get(ATTR_SUPPORTED_COLOR_MODES)
|
|
if not brightness_supported(supported_color_modes):
|
|
raise intent.IntentHandleError(
|
|
f"Entity {state.name} does not support changing brightness"
|
|
)
|
|
|
|
|
|
class SetIntentHandler(intent.IntentHandler):
|
|
"""Handle set color intents."""
|
|
|
|
intent_type = INTENT_SET
|
|
slot_schema = {
|
|
vol.Required("name"): cv.string,
|
|
vol.Optional("color"): color_util.color_name_to_rgb,
|
|
vol.Optional("brightness"): vol.All(vol.Coerce(int), vol.Range(0, 100)),
|
|
}
|
|
|
|
async def async_handle(self, intent_obj: intent.Intent) -> intent.IntentResponse:
|
|
"""Handle the hass intent."""
|
|
hass = intent_obj.hass
|
|
slots = self.async_validate_slots(intent_obj.slots)
|
|
state = hass.helpers.intent.async_match_state(
|
|
slots["name"]["value"], hass.states.async_all(DOMAIN)
|
|
)
|
|
|
|
service_data = {ATTR_ENTITY_ID: state.entity_id}
|
|
speech_parts = []
|
|
|
|
if "color" in slots:
|
|
_test_supports_color(state)
|
|
service_data[ATTR_RGB_COLOR] = slots["color"]["value"]
|
|
# Use original passed in value of the color because we don't have
|
|
# human readable names for that internally.
|
|
speech_parts.append(f"the color {intent_obj.slots['color']['value']}")
|
|
|
|
if "brightness" in slots:
|
|
_test_supports_brightness(state)
|
|
service_data[ATTR_BRIGHTNESS_PCT] = slots["brightness"]["value"]
|
|
speech_parts.append(f"{slots['brightness']['value']}% brightness")
|
|
|
|
await hass.services.async_call(
|
|
DOMAIN, SERVICE_TURN_ON, service_data, context=intent_obj.context
|
|
)
|
|
|
|
response = intent_obj.create_response()
|
|
|
|
if not speech_parts: # No attributes changed
|
|
speech = f"Turned on {state.name}"
|
|
else:
|
|
parts = [f"Changed {state.name} to"]
|
|
for index, part in enumerate(speech_parts):
|
|
if index == 0:
|
|
parts.append(f" {part}")
|
|
elif index != len(speech_parts) - 1:
|
|
parts.append(f", {part}")
|
|
else:
|
|
parts.append(f" and {part}")
|
|
speech = "".join(parts)
|
|
|
|
response.async_set_speech(speech)
|
|
return response
|