Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
AWS Lambda function for forwarding Alexa Intent requests to Home Assistant
# -*- coding: utf-8 -*-
import os
import json
import logging
import urllib3
_debug = bool(os.environ.get('DEBUG'))
_logger = logging.getLogger('HomeAssistant-Intents')
_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'
try:
token = event.get('session', {}).get('user', {}).get('accessToken')
except AttributeError:
token = None
if token is None and _debug:
token = os.environ.get('LONG_LIVED_ACCESS_TOKEN')
assert token, 'Could not get access token'
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'.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'))
@tiagofreire-pt

This comment has been minimized.

Copy link

tiagofreire-pt commented Dec 27, 2019

Hello.

I followed this guide: https://github.com/home-assistant/home-assistant.io/blob/current/source/_integrations/alexa.intent.markdown

But I only could get success on linking the account if I remove the 8123 port on all home assistant links, in lambda function and alexa app, and port forward on my router from external 443 to 8123. Otherwise, the lambda function returns:

[ERROR] AssertionError: Could not get access token
Traceback (most recent call last):
  File "/var/task/lambda_function.py", line 29, in lambda_handler
    assert token, 'Could not get access token'

Could you check the code or the guide for this, please?

@lpomfrey

This comment has been minimized.

Copy link
Owner Author

lpomfrey commented Dec 27, 2019

The guide and docs assume you've got an externally accessible Home Assistant instance, see the third requirement:

The Alexa Custom Skill API also needs your Home Assistant instance can be accessed from Internet. We strongly suggest you host HTTPS server and use validation certificate. Read more on our blog about how to set up encryption for Home Assistant. When running Hass.io using the Duck DNS add-on is the easiest method.

@tiagofreire-pt

This comment has been minimized.

Copy link

tiagofreire-pt commented Dec 27, 2019

Yes, it's accessible from the internet but it only works if the external port is 443, instead of the 8123 proposed in the tutorial.

@lpomfrey

This comment has been minimized.

Copy link
Owner Author

lpomfrey commented Dec 28, 2019

Yea, that's an Amazon requirement:

Note that the account linking URL must be a HTTPS URL on port 443, with a certificate from an Amazon approved CA authority (https://ccadb-public.secure.force.com/mozilla/IncludedCACertificateReport).
https://forums.developer.amazon.com/articles/38610/alexa-debugging-account-linking.html

It's actually noted on the Smart Home docs but not on the Custom Intent ones. I've submitted a pull request to clarify that on both.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.