Skip to content

Commit

Permalink
Make a generic Set intent for light
Browse files Browse the repository at this point in the history
  • Loading branch information
balloob committed Feb 24, 2018
1 parent 72053f6 commit 0c8281b
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 24 deletions.
60 changes: 44 additions & 16 deletions homeassistant/components/light/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@
vol.ExactSequence((str, cv.small_float, cv.small_float, cv.byte))
)

INTENT_SET_COLOR = 'HassLightSetColor'
INTENT_SET = 'HassLightSet'

_LOGGER = logging.getLogger(__name__)

Expand Down Expand Up @@ -248,13 +248,14 @@ def preprocess_turn_on_alternatives(params):
params[ATTR_BRIGHTNESS] = int(255 * brightness_pct/100)


class SetColorIntentHandler(intent.IntentHandler):
class SetIntentHandler(intent.IntentHandler):
"""Handle set color intents."""

intent_type = INTENT_SET_COLOR
intent_type = INTENT_SET
slot_schema = {
'name': cv.string,
'color': color_util.color_name_to_rgb
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):
Expand All @@ -265,19 +266,46 @@ async def async_handle(self, intent_obj):
slots['name']['value'],
[state for state in hass.states.async_all()
if state.domain == DOMAIN])
intent.async_test_feature(state, SUPPORT_RGB_COLOR, 'changing colors')

await hass.services.async_call(
DOMAIN, SERVICE_TURN_ON, {
ATTR_ENTITY_ID: state.entity_id,
ATTR_RGB_COLOR: slots['color']['value']
})
service_data = {
ATTR_ENTITY_ID: state.entity_id,
}
speech_parts = []

if 'color' in slots:
intent.async_test_feature(
state, SUPPORT_RGB_COLOR, 'changing colors')
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('the color {}'.format(
intent_obj.slots['color']['value']))

if 'brightness' in slots:
intent.async_test_feature(
state, SUPPORT_BRIGHTNESS, 'changing brightness')
service_data[ATTR_BRIGHTNESS_PCT] = slots['brightness']['value']
speech_parts.append('{}% brightness'.format(
slots['brightness']['value']))

await hass.services.async_call(DOMAIN, SERVICE_TURN_ON, service_data)

# Use original passed in value of the color because we don't have human
# readable names for that internally.
response = intent_obj.create_response()
response.async_set_speech('Changed the color of {} to {}'.format(
state.name, intent_obj.slots['color']['value']))

if len(speech_parts) == 0:
speech = 'Turned on {}'.format(state.name)
else:
parts = ['Changed {} to'.format(state.name)]
for index, part in enumerate(speech_parts):
if index == 0:
parts.append(' {}'.format(part))
elif index != len(speech_parts) - 1:
parts.append(', {}'.format(part))
else:
parts.append(' and {}'.format(part))
speech = ''.join(parts)

response.async_set_speech(speech)
return response


Expand Down Expand Up @@ -332,7 +360,7 @@ async def async_handle_light_service(service):
DOMAIN, SERVICE_TOGGLE, async_handle_light_service,
schema=LIGHT_TOGGLE_SCHEMA)

hass.helpers.intent.async_register(SetColorIntentHandler())
hass.helpers.intent.async_register(SetIntentHandler())

return True

Expand Down
4 changes: 3 additions & 1 deletion homeassistant/helpers/intent.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ async def async_handle(hass, platform, intent_type, slots=None,
result = await handler.async_handle(intent)
return result
except vol.Invalid as err:
_LOGGER.warning('Received invalid slot info for %s: %s',
intent_type, err)
raise InvalidSlotInfo(
'Received invalid slot info for {}'.format(intent_type)) from err
except IntentHandleError:
Expand Down Expand Up @@ -167,7 +169,7 @@ class ServiceIntentHandler(IntentHandler):
"""

slot_schema = {
'name': cv.string,
vol.Required('name'): cv.string,
}

def __init__(self, intent_type, domain, service, speech):
Expand Down
49 changes: 42 additions & 7 deletions tests/components/light/test_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -306,17 +306,17 @@ def test_light_profiles(self):
data)


async def test_set_color_intent(hass):
async def test_intent_set_color(hass):
"""Test the set color intent."""
hass.states.async_set('light.hello_2', 'off', {
ATTR_SUPPORTED_FEATURES: light.SUPPORT_RGB_COLOR
})
hass.states.async_set('switch.hello', 'off')
calls = async_mock_service(hass, light.DOMAIN, light.SERVICE_TURN_ON)
hass.helpers.intent.async_register(light.SetColorIntentHandler())
hass.helpers.intent.async_register(light.SetIntentHandler())

result = await hass.helpers.intent.async_handle(
'test', light.INTENT_SET_COLOR, {
'test', light.INTENT_SET, {
'name': {
'value': 'Hello',
},
Expand All @@ -327,7 +327,7 @@ async def test_set_color_intent(hass):
await hass.async_block_till_done()

assert result.speech['plain']['speech'] == \
'Changed the color of hello 2 to blue'
'Changed hello 2 to the color blue'

assert len(calls) == 1
call = calls[0]
Expand All @@ -337,15 +337,15 @@ async def test_set_color_intent(hass):
assert call.data.get(light.ATTR_RGB_COLOR) == (0, 0, 255)


async def test_set_color_intent_tests_feature(hass):
async def test_intent_set_color_tests_feature(hass):
"""Test the set color intent."""
hass.states.async_set('light.hello', 'off')
calls = async_mock_service(hass, light.DOMAIN, light.SERVICE_TURN_ON)
hass.helpers.intent.async_register(light.SetColorIntentHandler())
hass.helpers.intent.async_register(light.SetIntentHandler())

try:
await hass.helpers.intent.async_handle(
'test', light.INTENT_SET_COLOR, {
'test', light.INTENT_SET, {
'name': {
'value': 'Hello',
},
Expand All @@ -358,3 +358,38 @@ async def test_set_color_intent_tests_feature(hass):
assert str(err) == 'Entity hello does not support changing colors'

assert len(calls) == 0


async def test_intent_set_color_and_brightness(hass):
"""Test the set color intent."""
hass.states.async_set('light.hello_2', 'off', {
ATTR_SUPPORTED_FEATURES: (
light.SUPPORT_RGB_COLOR | light.SUPPORT_BRIGHTNESS)
})
hass.states.async_set('switch.hello', 'off')
calls = async_mock_service(hass, light.DOMAIN, light.SERVICE_TURN_ON)
hass.helpers.intent.async_register(light.SetIntentHandler())

result = await hass.helpers.intent.async_handle(
'test', light.INTENT_SET, {
'name': {
'value': 'Hello',
},
'color': {
'value': 'blue'
},
'brightness': {
'value': '20'
}
})
await hass.async_block_till_done()

assert result.speech['plain']['speech'] == \
'Changed hello 2 to the color blue and 20% brightness'

assert len(calls) == 1
call = calls[0]
assert call.domain == light.DOMAIN
assert call.service == SERVICE_TURN_ON
assert call.data.get(ATTR_ENTITY_ID) == 'light.hello_2'
assert call.data.get(light.ATTR_RGB_COLOR) == (0, 0, 255)

0 comments on commit 0c8281b

Please sign in to comment.