diff --git a/homeassistant/components/conversation.py b/homeassistant/components/conversation.py index 9f6360361f1..591190383a0 100644 --- a/homeassistant/components/conversation.py +++ b/homeassistant/components/conversation.py @@ -14,11 +14,13 @@ from homeassistant import core from homeassistant.const import ( ATTR_ENTITY_ID, SERVICE_TURN_OFF, SERVICE_TURN_ON) import homeassistant.helpers.config_validation as cv +from homeassistant.helpers import script + REQUIREMENTS = ['fuzzywuzzy==0.15.0'] ATTR_TEXT = 'text' - +ATTR_SENTENCE = 'sentence' DOMAIN = 'conversation' REGEX_TURN_COMMAND = re.compile(r'turn (?P(?: |\w)+) (?P\w+)') @@ -29,9 +31,12 @@ SERVICE_PROCESS_SCHEMA = vol.Schema({ vol.Required(ATTR_TEXT): vol.All(cv.string, vol.Lower), }) -CONFIG_SCHEMA = vol.Schema({ - DOMAIN: vol.Schema({}), -}, extra=vol.ALLOW_EXTRA) +CONFIG_SCHEMA = vol.Schema({DOMAIN: vol.Schema({ + cv.string: vol.Schema({ + vol.Required(ATTR_SENTENCE): cv.string, + vol.Required('action'): cv.SCRIPT_SCHEMA, + }) +})}, extra=vol.ALLOW_EXTRA) def setup(hass, config): @@ -40,9 +45,30 @@ def setup(hass, config): from fuzzywuzzy import process as fuzzyExtract logger = logging.getLogger(__name__) + config = config.get(DOMAIN, {}) + + choices = {attrs[ATTR_SENTENCE]: script.Script( + hass, + attrs['action'], + name) + for name, attrs in config.items()} def process(service): """Parse text into commands.""" + # if actually configured + if choices: + text = service.data[ATTR_TEXT] + match = fuzzyExtract.extractOne(text, choices.keys()) + scorelimit = 60 # arbitrary value + logging.info( + 'matched up text %s and found %s', + text, + [match[0] if match[1] > scorelimit else 'nothing'] + ) + if match[1] > scorelimit: + choices[match[0]].run() # run respective script + return + text = service.data[ATTR_TEXT] match = REGEX_TURN_COMMAND.match(text) diff --git a/tests/components/test_conversation.py b/tests/components/test_conversation.py index 76d582c8856..65ce95ee8e9 100644 --- a/tests/components/test_conversation.py +++ b/tests/components/test_conversation.py @@ -117,3 +117,46 @@ class TestConversation(unittest.TestCase): conversation.DOMAIN, 'process', event_data, True)) self.assertTrue(mock_logger.called) self.assertFalse(mock_call.called) + + +class TestConfiguration(unittest.TestCase): + """Test the conversation configuration component.""" + + # pylint: disable=invalid-name + def setUp(self): + """Setup things to be run when tests are started.""" + self.hass = get_test_home_assistant() + self.assertTrue(setup_component(self.hass, conversation.DOMAIN, { + conversation.DOMAIN: { + 'test_2': { + 'sentence': 'switch boolean', + 'action': { + 'service': 'input_boolean.toggle' + } + } + } + })) + + # pylint: disable=invalid-name + def tearDown(self): + """Stop everything that was started.""" + self.hass.stop() + + def test_custom(self): + """Setup and perform good turn on requests.""" + calls = [] + + @callback + def record_call(service): + """Recorder for a call.""" + calls.append(service) + + self.hass.services.register('input_boolean', 'toggle', record_call) + + event_data = {conversation.ATTR_TEXT: 'switch boolean'} + self.assertTrue(self.hass.services.call( + conversation.DOMAIN, 'process', event_data, True)) + + call = calls[-1] + self.assertEqual('input_boolean', call.domain) + self.assertEqual('toggle', call.service)