def test_service_call(self): """Test service call with templating.""" config = { "service": "{{ 'test_domain.test_service' }}", "entity_id": "hello.world", "data": { "hello": "{{ 'goodbye' }}", "effect": { "value": "{{ 'complex' }}", "simple": "simple" }, }, "data_template": { "list": ["{{ 'list' }}", "2"] }, "target": { "area_id": "test-area-id", "entity_id": "will.be_overridden" }, } service.call_from_config(self.hass, config) self.hass.block_till_done() assert dict(self.calls[0].data) == { "hello": "goodbye", "effect": { "value": "complex", "simple": "simple", }, "list": ["list", "2"], "entity_id": ["hello.world"], "area_id": ["test-area-id"], }
def test_template_service_call(self): """Test service call with tempating.""" config = { 'service_template': '{{ \'test_domain.test_service\' }}', 'entity_id': 'hello.world', 'data_template': { 'hello': '{{ \'goodbye\' }}', 'data': { 'value': '{{ \'complex\' }}', 'simple': 'simple' }, 'list': ['{{ \'list\' }}', '2'], }, } runs = [] decor = service.service('test_domain', 'test_service') decor(lambda x, y: runs.append(y)) service.call_from_config(self.hass, config) self.hass.pool.block_till_done() self.assertEqual('goodbye', runs[0].data['hello']) self.assertEqual('complex', runs[0].data['data']['value']) self.assertEqual('simple', runs[0].data['data']['simple']) self.assertEqual('list', runs[0].data['list'][0])
def _handle_alexa(handler, path_match, data): """Handle Alexa.""" _LOGGER.debug('Received Alexa request: %s', data) req = data.get('request') if req is None: _LOGGER.error('Received invalid data from Alexa: %s', data) handler.write_json_message( "Invalid value received for port", HTTP_UNPROCESSABLE_ENTITY) return req_type = req['type'] if req_type == 'SessionEndedRequest': handler.send_response(HTTP_OK) handler.end_headers() return intent = req.get('intent') response = AlexaResponse(handler.server.hass, intent) if req_type == 'LaunchRequest': response.add_speech( SpeechType.plaintext, "Hello, and welcome to the future. How may I help?") handler.write_json(response.as_dict()) return if req_type != 'IntentRequest': _LOGGER.warning('Received unsupported request: %s', req_type) return intent_name = intent['name'] config = _CONFIG.get(intent_name) if config is None: _LOGGER.warning('Received unknown intent %s', intent_name) response.add_speech( SpeechType.plaintext, "This intent is not yet configured within Home Assistant.") handler.write_json(response.as_dict()) return speech = config.get(CONF_SPEECH) card = config.get(CONF_CARD) action = config.get(CONF_ACTION) # pylint: disable=unsubscriptable-object if speech is not None: response.add_speech(SpeechType[speech['type']], speech['text']) if card is not None: response.add_card(CardType[card['type']], card['title'], card['content']) if action is not None: call_from_config(handler.server.hass, action, True) handler.write_json(response.as_dict())
def test_not_mutate_input(self): orig = {"service": "test_domain.test_service", "entity_id": "hello.world, sensor.beer", "data": {"hello": 1}} service.call_from_config(self.hass, orig) self.hass.pool.block_till_done() self.assertEqual( {"service": "test_domain.test_service", "entity_id": "hello.world, sensor.beer", "data": {"hello": 1}}, orig )
def _call_service(self, service_name, service_data=None, allow_override=False): """Call either a specified or active child's service.""" if service_data is None: service_data = {} if allow_override and service_name in self._cmds: call_from_config(self.hass, self._cmds[service_name], variables=service_data, blocking=True) return active_child = self._child_state if active_child is None: # No child to call service on return service_data[ATTR_ENTITY_ID] = active_child.entity_id self.hass.services.call(DOMAIN, service_name, service_data, blocking=True)
def _handle_alexa(handler, path_match, data): """Handle Alexa.""" _LOGGER.debug('Received Alexa request: %s', data) req = data.get('request') if req is None: _LOGGER.error('Received invalid data from Alexa: %s', data) handler.write_json_message("Invalid value received for port", HTTP_UNPROCESSABLE_ENTITY) return req_type = req['type'] if req_type == 'SessionEndedRequest': handler.send_response(HTTP_OK) handler.end_headers() return intent = req.get('intent') response = AlexaResponse(handler.server.hass, intent) if req_type == 'LaunchRequest': response.add_speech( SpeechType.plaintext, "Hello, and welcome to the future. How may I help?") handler.write_json(response.as_dict()) return if req_type != 'IntentRequest': _LOGGER.warning('Received unsupported request: %s', req_type) return intent_name = intent['name'] config = _CONFIG.get(intent_name) if config is None: _LOGGER.warning('Received unknown intent %s', intent_name) response.add_speech( SpeechType.plaintext, "This intent is not yet configured within Home Assistant.") handler.write_json(response.as_dict()) return speech = config.get(CONF_SPEECH) card = config.get(CONF_CARD) action = config.get(CONF_ACTION) # pylint: disable=unsubscriptable-object if speech is not None: response.add_speech(SpeechType[speech['type']], speech['text']) if card is not None: response.add_card(CardType[card['type']], card['title'], card['content']) if action is not None: call_from_config(handler.server.hass, action, True) handler.write_json(response.as_dict())
def test_template_service_call(self): """Test service call with tempating.""" config = { 'service_template': '{{ \'test_domain.test_service\' }}', 'entity_id': 'hello.world', 'data_template': { 'hello': '{{ \'goodbye\' }}', 'data': { 'value': '{{ \'complex\' }}', 'simple': 'simple' }, 'list': ['{{ \'list\' }}', '2'], }, } runs = [] decor = service.service('test_domain', 'test_service') decor(lambda x, y: runs.append(y)) service.call_from_config(self.hass, config) self.hass.block_till_done() self.assertEqual('goodbye', runs[0].data['hello']) self.assertEqual('complex', runs[0].data['data']['value']) self.assertEqual('simple', runs[0].data['data']['simple']) self.assertEqual('list', runs[0].data['list'][0])
def test_split_entity_string(self): service.call_from_config(self.hass, { 'service': 'test_domain.test_service', 'entity_id': 'hello.world, sensor.beer' }) self.hass.pool.block_till_done() self.assertEqual(['hello.world', 'sensor.beer'], self.calls[-1].data.get('entity_id'))
def _call_service(self, action, variables): """Call the service specified in the action.""" self.last_action = action.get(CONF_ALIAS, 'call service') self._log("Executing step %s" % self.last_action) service.call_from_config(self.hass, action, True, variables, validate_config=False)
def test_split_entity_string(self): """Test splitting of entity string.""" service.call_from_config(self.hass, { 'service': 'test_domain.test_service', 'entity_id': 'hello.world, sensor.beer' }) self.hass.block_till_done() self.assertEqual(['hello.world', 'sensor.beer'], self.calls[-1].data.get('entity_id'))
def test_split_entity_string(self): """Test splitting of entity string.""" service.call_from_config(self.hass, { 'service': 'test_domain.test_service', 'entity_id': 'hello.world, sensor.beer' }) self.hass.block_till_done() assert ['hello.world', 'sensor.beer'] == \ self.calls[-1].data.get('entity_id')
def test_split_entity_string(self): """Test splitting of entity string.""" service.call_from_config( self.hass, { "service": "test_domain.test_service", "entity_id": "hello.world, sensor.beer", }, ) self.hass.block_till_done() assert ["hello.world", "sensor.beer"] == self.calls[-1].data.get("entity_id")
def test_service_template_service_call(self): """Test legacy service_template call with templating.""" config = { "service_template": "{{ 'test_domain.test_service' }}", "entity_id": "hello.world", "data": {"hello": "goodbye"}, } service.call_from_config(self.hass, config) self.hass.block_till_done() assert self.calls[0].data["hello"] == "goodbye"
def _call_service(self, service_name, service_data=None, allow_override=False): """Call either a specified or active child's service.""" if service_data is None: service_data = {} if allow_override and service_name in self._cmds: call_from_config(self.hass, self._cmds[service_name], variables=service_data, blocking=True) return active_child = self._child_state service_data[ATTR_ENTITY_ID] = active_child.entity_id self.hass.services.call(DOMAIN, service_name, service_data, blocking=True)
def _call_service(self, action): """ Calls the service specified in the action. """ # Backwards compatibility if CONF_SERVICE not in action and CONF_SERVICE_OLD in action: action[CONF_SERVICE] = action[CONF_SERVICE_OLD] if CONF_SERVICE_DATA not in action and CONF_SERVICE_DATA_OLD in action: action[CONF_SERVICE_DATA] = action[CONF_SERVICE_DATA_OLD] self._last_action = action.get(CONF_ALIAS, action[CONF_SERVICE]) _LOGGER.info("Executing script %s step %s", self._name, self._last_action) call_from_config(self.hass, action, True)
def test_not_mutate_input(self): orig = { 'service': 'test_domain.test_service', 'entity_id': 'hello.world, sensor.beer', 'data': { 'hello': 1, }, } service.call_from_config(self.hass, orig) self.hass.pool.block_till_done() self.assertEqual({ 'service': 'test_domain.test_service', 'entity_id': 'hello.world, sensor.beer', 'data': { 'hello': 1, }, }, orig)
def test_passing_variables_to_templates(self): """Test passing variables to templates.""" config = { 'service_template': '{{ var_service }}', 'entity_id': 'hello.world', 'data_template': { 'hello': '{{ var_data }}', }, } service.call_from_config(self.hass, config, variables={ 'var_service': 'test_domain.test_service', 'var_data': 'goodbye', }) self.hass.block_till_done() self.assertEqual('goodbye', self.calls[0].data['hello'])
def test_not_mutate_input(self): """Test for immutable input.""" config = cv.SERVICE_SCHEMA( { "service": "test_domain.test_service", "entity_id": "hello.world, sensor.beer", "data": {"hello": 1}, "data_template": {"nested": {"value": "{{ 1 + 1 }}"}}, } ) orig = deepcopy(config) # Only change after call is each template getting hass attached template.attach(self.hass, orig) service.call_from_config(self.hass, config, validate_config=False) assert orig == config
def test_bad_template(self): """Test passing bad template.""" config = { 'service_template': '{{ var_service }}', 'entity_id': 'hello.world', 'data_template': { 'hello': '{{ states + unknown_var }}' } } service.call_from_config(self.hass, config, variables={ 'var_service': 'test_domain.test_service', 'var_data': 'goodbye', }) self.hass.block_till_done() assert len(self.calls) == 0
def test_template_service_call(self): """Test service call with tempating.""" config = { 'service_template': '{{ \'test_domain.test_service\' }}', 'entity_id': 'hello.world', 'data_template': { 'hello': '{{ \'goodbye\' }}', }, } runs = [] decor = service.service('test_domain', 'test_service') decor(lambda x, y: runs.append(y)) service.call_from_config(self.hass, config) self.hass.pool.block_till_done() self.assertEqual('goodbye', runs[0].data['hello'])
def test_not_mutate_input(self): """Test for immutable input.""" orig = { 'service': 'test_domain.test_service', 'entity_id': 'hello.world, sensor.beer', 'data': { 'hello': 1, }, } service.call_from_config(self.hass, orig) self.hass.pool.block_till_done() self.assertEqual({ 'service': 'test_domain.test_service', 'entity_id': 'hello.world, sensor.beer', 'data': { 'hello': 1, }, }, orig)
def test_passing_variables_to_templates(self): """Test passing variables to templates.""" config = { "service_template": "{{ var_service }}", "entity_id": "hello.world", "data_template": {"hello": "{{ var_data }}"}, } service.call_from_config( self.hass, config, variables={ "var_service": "test_domain.test_service", "var_data": "goodbye", }, ) self.hass.block_till_done() assert "goodbye" == self.calls[0].data["hello"]
def test_bad_template(self): """Test passing bad template.""" config = { "service_template": "{{ var_service }}", "entity_id": "hello.world", "data_template": {"hello": "{{ states + unknown_var }}"}, } service.call_from_config( self.hass, config, variables={ "var_service": "test_domain.test_service", "var_data": "goodbye", }, ) self.hass.block_till_done() assert len(self.calls) == 0
def test_template_service_call(self): """Test service call with templating.""" config = { "service_template": "{{ 'test_domain.test_service' }}", "entity_id": "hello.world", "data_template": { "hello": "{{ 'goodbye' }}", "data": {"value": "{{ 'complex' }}", "simple": "simple"}, "list": ["{{ 'list' }}", "2"], }, } service.call_from_config(self.hass, config) self.hass.block_till_done() assert "goodbye" == self.calls[0].data["hello"] assert "complex" == self.calls[0].data["data"]["value"] assert "simple" == self.calls[0].data["data"]["simple"] assert "list" == self.calls[0].data["list"][0]
def test_not_mutate_input(self): """Test for immutable input.""" config = cv.SERVICE_SCHEMA({ 'service': 'test_domain.test_service', 'entity_id': 'hello.world, sensor.beer', 'data': { 'hello': 1, }, 'data_template': { 'nested': { 'value': '{{ 1 + 1 }}' } } }) orig = deepcopy(config) # Only change after call is each template getting hass attached template.attach(self.hass, orig) service.call_from_config(self.hass, config, validate_config=False) assert orig == config
def test_passing_variables_to_templates(self): """Test passing variables to templates.""" config = { 'service_template': '{{ var_service }}', 'entity_id': 'hello.world', 'data_template': { 'hello': '{{ var_data }}', }, } runs = [] decor = service.service('test_domain', 'test_service') decor(lambda x, y: runs.append(y)) service.call_from_config(self.hass, config, variables={ 'var_service': 'test_domain.test_service', 'var_data': 'goodbye', }) self.hass.pool.block_till_done() self.assertEqual('goodbye', runs[0].data['hello'])
def test_template_service_call(self): """Test service call with tempating.""" config = { 'service_template': '{{ \'test_domain.test_service\' }}', 'entity_id': 'hello.world', 'data_template': { 'hello': '{{ \'goodbye\' }}', 'data': { 'value': '{{ \'complex\' }}', 'simple': 'simple' }, 'list': ['{{ \'list\' }}', '2'], }, } service.call_from_config(self.hass, config) self.hass.block_till_done() self.assertEqual('goodbye', self.calls[0].data['hello']) self.assertEqual('complex', self.calls[0].data['data']['value']) self.assertEqual('simple', self.calls[0].data['data']['simple']) self.assertEqual('list', self.calls[0].data['list'][0])
def test_template_service_call(self): """Test service call with templating.""" config = { 'service_template': '{{ \'test_domain.test_service\' }}', 'entity_id': 'hello.world', 'data_template': { 'hello': '{{ \'goodbye\' }}', 'data': { 'value': '{{ \'complex\' }}', 'simple': 'simple' }, 'list': ['{{ \'list\' }}', '2'], }, } service.call_from_config(self.hass, config) self.hass.block_till_done() assert 'goodbye' == self.calls[0].data['hello'] assert 'complex' == self.calls[0].data['data']['value'] assert 'simple' == self.calls[0].data['data']['simple'] assert 'list' == self.calls[0].data['list'][0]
def test_fail_silently_if_no_service(self, mock_log): service.call_from_config(self.hass, None) self.assertEqual(1, mock_log.call_count) service.call_from_config(self.hass, {}) self.assertEqual(2, mock_log.call_count) service.call_from_config(self.hass, {"service": "invalid"}) self.assertEqual(3, mock_log.call_count)
def test_fail_silently_if_no_service(self, mock_log): service.call_from_config(self.hass, None) self.assertEqual(1, mock_log.call_count) service.call_from_config(self.hass, {}) self.assertEqual(2, mock_log.call_count) service.call_from_config(self.hass, {'service': 'invalid'}) self.assertEqual(3, mock_log.call_count)
def test_fail_silently_if_no_service(self, mock_log): """Test failing if service is missing.""" service.call_from_config(self.hass, None) assert 1 == mock_log.call_count service.call_from_config(self.hass, {}) assert 2 == mock_log.call_count service.call_from_config(self.hass, {"service": "invalid"}) assert 3 == mock_log.call_count
def test_fail_silently_if_no_service(self, mock_log): """Test failling if service is missing.""" service.call_from_config(self.hass, None) self.assertEqual(1, mock_log.call_count) service.call_from_config(self.hass, {}) self.assertEqual(2, mock_log.call_count) service.call_from_config(self.hass, { 'service': 'invalid' }) self.assertEqual(3, mock_log.call_count)
def test_fail_silently_if_no_service(self, mock_log): """Test failing if service is missing.""" service.call_from_config(self.hass, None) assert 1 == mock_log.call_count service.call_from_config(self.hass, {}) assert 2 == mock_log.call_count service.call_from_config(self.hass, { 'service': 'invalid' }) assert 3 == mock_log.call_count
def turn_off(self, **kwargs): """ Fires the off action. """ call_from_config(self.hass, self._off_action, True)
def action(): """Action to be executed.""" _LOGGER.info('Executing %s', name) logbook.log_entry(hass, name, 'has been triggered', DOMAIN) call_from_config(hass, config)
def turn_on(self, **kwargs): """Fire the on action.""" call_from_config(self.hass, self._on_action, True)
def test_service_call(self): """Test service call with templating.""" config = { "service": "{{ 'test_domain.test_service' }}", "entity_id": "hello.world", "data": { "hello": "{{ 'goodbye' }}", "effect": { "value": "{{ 'complex' }}", "simple": "simple" }, }, "data_template": { "list": ["{{ 'list' }}", "2"] }, "target": { "area_id": "test-area-id", "entity_id": "will.be_overridden" }, } service.call_from_config(self.hass, config) self.hass.block_till_done() assert dict(self.calls[0].data) == { "hello": "goodbye", "effect": { "value": "complex", "simple": "simple", }, "list": ["list", "2"], "entity_id": ["hello.world"], "area_id": ["test-area-id"], } config = { "service": "{{ 'test_domain.test_service' }}", "target": { "area_id": ["area-42", "{{ 'area-51' }}"], "device_id": ["abcdef", "{{ 'fedcba' }}"], "entity_id": ["light.static", "{{ 'light.dynamic' }}"], }, } service.call_from_config(self.hass, config) self.hass.block_till_done() assert dict(self.calls[1].data) == { "area_id": ["area-42", "area-51"], "device_id": ["abcdef", "fedcba"], "entity_id": ["light.static", "light.dynamic"], } config = { "service": "{{ 'test_domain.test_service' }}", "target": "{{ var_target }}", } service.call_from_config( self.hass, config, variables={ "var_target": { "entity_id": "light.static", "area_id": ["area-42", "area-51"], }, }, ) service.call_from_config(self.hass, config) self.hass.block_till_done() assert dict(self.calls[2].data) == { "area_id": ["area-42", "area-51"], "entity_id": ["light.static"], }
def call(self, action): if action not in self.actions: return call_from_config(self.hass, self.actions[action], blocking=True)
def turn_off(self, **kwargs): """Fire the off action.""" call_from_config(self.hass, self._off_action, True)
def _call_service(self, action): """Call the service specified in the action.""" self._last_action = action.get(CONF_ALIAS, 'call service') _LOGGER.info("Executing script %s step %s", self._name, self._last_action) call_from_config(self.hass, action, True)
def turn_on(self, **kwargs): """Fires the on action.""" call_from_config(self.hass, self._on_action, True)
def test_split_entity_string(self): service.call_from_config( self.hass, {"service": "test_domain.test_service", "entity_id": "hello.world, sensor.beer"} ) self.hass.pool.block_till_done() self.assertEqual(["hello.world", "sensor.beer"], self.calls[-1].data.get("entity_id"))