Last active
March 14, 2024 19:26
-
-
Save awarecan/630510a9742f5f8901b5ab284c25e912 to your computer and use it in GitHub Desktop.
Alexa Smart Home Skill Adapter for Home Assistant
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| """ | |
| Copyright 2019 Jason Hu <awaregit at gmail.com> | |
| Licensed under the Apache License, Version 2.0 (the "License"); | |
| you may not use this file except in compliance with the License. | |
| You may obtain a copy of the License at | |
| http://www.apache.org/licenses/LICENSE-2.0 | |
| Unless required by applicable law or agreed to in writing, software | |
| distributed under the License is distributed on an "AS IS" BASIS, | |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| See the License for the specific language governing permissions and | |
| limitations under the License. | |
| """ | |
| import os | |
| import json | |
| import logging | |
| import urllib3 | |
| _debug = bool(os.environ.get('DEBUG')) | |
| _logger = logging.getLogger('HomeAssistant-SmartHome') | |
| _logger.setLevel(logging.DEBUG if _debug else logging.INFO) | |
| def lambda_handler(event, context): | |
| """Handle incoming Alexa directive.""" | |
| _logger.debug('Event: %s', event) | |
| base_url = os.environ.get('BASE_URL') | |
| assert base_url is not None, 'Please set BASE_URL environment variable' | |
| directive = event.get('directive') | |
| assert directive is not None, 'Malformatted request - missing directive' | |
| assert directive.get('header', {}).get('payloadVersion') == '3', \ | |
| 'Only support payloadVersion == 3' | |
| scope = directive.get('endpoint', {}).get('scope') | |
| if scope is None: | |
| # token is in payload.scope for Discovery directive | |
| scope = directive.get('payload', {}).get('scope') | |
| if scope is None: | |
| # token is in payload.grantee for AcceptGrant directive | |
| scope = directive.get('payload', {}).get('grantee') | |
| assert scope is not None, 'Malformatted request - missing endpoint.scope' | |
| assert scope.get('type') == 'BearerToken', 'Only support BearerToken' | |
| token = scope.get('token') | |
| if token is None and _debug: | |
| token = os.environ.get('LONG_LIVED_ACCESS_TOKEN') # only for debug purpose | |
| verify_ssl = not bool(os.environ.get('NOT_VERIFY_SSL')) | |
| http = urllib3.PoolManager( | |
| cert_reqs='CERT_REQUIRED' if verify_ssl else 'CERT_NONE', | |
| timeout=urllib3.Timeout(connect=2.0, read=10.0) | |
| ) | |
| response = http.request( | |
| 'POST', | |
| '{}/api/alexa/smart_home'.format(base_url), | |
| headers={ | |
| 'Authorization': 'Bearer {}'.format(token), | |
| 'Content-Type': 'application/json', | |
| }, | |
| body=json.dumps(event).encode('utf-8'), | |
| ) | |
| if response.status >= 400: | |
| return { | |
| 'event': { | |
| 'payload': { | |
| 'type': 'INVALID_AUTHORIZATION_CREDENTIAL' | |
| if response.status in (401, 403) else 'INTERNAL_ERROR', | |
| 'message': response.data.decode("utf-8"), | |
| } | |
| } | |
| } | |
| return json.loads(response.data.decode('utf-8')) |
Author
Hi,
Tried this several times with different combinations of credentials.
My Log from HA.
Log Details (ERROR)
Logger: aiohttp.server
Source: components/alexa/capabilities.py:1478
First occurred: 13:52:58 (2 occurrences)
Last logged: 13:53:17
Error handling request
Traceback (most recent call last):
File "/usr/local/lib/python3.7/site-packages/aiohttp/web_protocol.py", line 418, in start
resp = await task
File "/usr/local/lib/python3.7/site-packages/aiohttp/web_app.py", line 458, in _handle
resp = await handler(request)
File "/usr/local/lib/python3.7/site-packages/aiohttp/web_middlewares.py", line 119, in impl
return await handler(request)
File "/usr/src/homeassistant/homeassistant/components/http/real_ip.py", line 39, in real_ip_middleware
return await handler(request)
File "/usr/src/homeassistant/homeassistant/components/http/ban.py", line 73, in ban_middleware
return await handler(request)
File "/usr/src/homeassistant/homeassistant/components/http/auth.py", line 127, in auth_middleware
return await handler(request)
File "/usr/src/homeassistant/homeassistant/components/http/view.py", line 125, in handle
result = await result
File "/usr/src/homeassistant/homeassistant/components/alexa/smart_home_http.py", line 120, in post
hass, self.smart_home_config, message, context=core.Context(user_id=user.id)
File "/usr/src/homeassistant/homeassistant/components/alexa/smart_home.py", line 39, in async_handle_message
response = await funct_ref(hass, config, directive, context)
File "/usr/src/homeassistant/homeassistant/components/alexa/handlers.py", line 84, in async_api_discovery
for alexa_entity in async_get_entities(hass, config)
File "/usr/src/homeassistant/homeassistant/components/alexa/handlers.py", line 85, in <listcomp>
if config.should_expose(alexa_entity.entity_id)
File "/usr/src/homeassistant/homeassistant/components/alexa/entities.py", line 285, in serialize_discovery
for i in self.interfaces()
File "/usr/src/homeassistant/homeassistant/components/alexa/entities.py", line 286, in <listcomp>
if locale in i.supported_locales
File "/usr/src/homeassistant/homeassistant/components/alexa/capabilities.py", line 205, in serialize_discovery
capability_resources = self.capability_resources()
File "/usr/src/homeassistant/homeassistant/components/alexa/capabilities.py", line 1478, in capability_resources
min_value = float(self.entity.attributes[input_number.ATTR_MIN])
KeyError: 'min'
And my output from Lambda
{
"event": {
"payload": {
"type": "INTERNAL_ERROR",
"message": "500 Internal Server Error\n\nServer got itself in trouble"
}
}
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Updated per community suggestion - have not tested by myself yet.