Integrating Alexa with your self-hosted Home Assistant instance can be a powerful way to control your smart home using voice commands. This guide offers a detailed walkthrough, covering the creation of an AWS Lambda function, the development of an Alexa skill, and the configuration of account linking, based on a successfully implemented setup.
Prerequisites
- A publicly accessible Home Assistant instance with HTTPS. SSLChecker can be used to detect issues with your certificate.
- An AWS account.
- An Alexa developer console account.
- Basic knowledge of Home Assistant and AWS services.
Step 1: Set Up AWS Lambda
An IAM Role needs to be assigned to the new Lambda function. The Role can be created separately as described below or directly when the Lambda function is created.
Create an IAM Role for the Lambda
- Log in to the AWS Management Console.
- Navigate to IAM > Role and create a new Rolle.
- Select
AWS-Service
as the trusted entity type,Lambda
asAWSLambdaBasicExecutionRole
.
Create a Lambda Function
Note: Alexa Skills are only supported in specific AWS regions.
US West (Oregon) region for Japanese and English (AU) skills.
US East (N.Virginia) region for English (US) or English (CA) skills
EU (Ireland) region for English (UK), English (IN), German (DE), Spanish (ES) or French (FR) skills.
- Navigate to Lambda and click on
Create function
. - Choose
Author from scratch
and provide:- Function name:
Homeassistant
- Runtime:
Python 3.9
- Permission: Your created IAM role
- Function name:
- Click
Create function
. - Replace the content of the default
lambda_function.py
file with the code below. - Navigate to the
Configuration
tab, then selectEnvironment variables
and configure yourBASE_URL
(without trailing slash) - Deploy the function
"""
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'
base_url = base_url.strip("/")
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 grantee for Linking directive
scope = directive.get('payload', {}).get('grantee')
if scope is None:
# token is in payload for Discovery directive
scope = directive.get('payload', {}).get('scope')
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"),
}
}
}
_logger.debug('Response: %s', response.data.decode("utf-8"))
return json.loads(response.data.decode('utf-8'))
Step 2: Create an Alexa Skill
After the AWS Lambda function is created, an Alexa Skill that triggers the function can be created.
Set Up the Skill in the Alexa Developer Console
- Go to the Alexa Developer Console.
- Click
Create Skill.
- Provide a name for your skill (e.g.,
Home Assistant Integration
). - Choose
Smart Home
as the skill type and clickCreate Skill
.
Configure the Endpoint
- In the Smart Home section, go to Endpoint.
- Choose
AWS Lambda ARN
as the endpoint type. - Enter your Lambda Function ARN (e.g.,
arn:aws:lambda:eu-west-1:xxxxxxx:function:Homeassistant
).
Account Linking
Alexa needs to link your Amazon account to your Home Assistant account to ensure that only authenticated Alexa requests can access your home’s devices. Therefore configure your home assistant instance in the Account Linking section as following.
- Authorization URL:
https://your-domain/auth/authorize
- Token URL:
https://your-domain/auth/token
- Client ID:
https://pitangui.amazon.com/
if you are in UShttps://layla.amazon.com/
if you are in EUhttps://alexa.amazon.co.jp/
if you are in JP and AU
- Client Secret: Generate and store securely.
- Authentication Scheme:
Credentials in request body
- Scope:
smart_home
Step 3: Add a trigger to AWS Lambda
Switch back to the AWS Lambda you created and click on Add trigger
.
Choose Alexa
as a trigger and Alexa smart home
as an Alexa product.
Enter the Skill ID of your created Alexa Skill.
Step 4: Configure Home Assistant
Connect to your Home Assistant instance and enable Alexa in the configuration.yaml
The filter configuration field can be used to include or exclude entities.
Restart the Home Assistant instance.
alexa:
smart_home:
client_id: "https://layla.amazon.com/"
client_secret: "******"
locale: de-DE
endpoint: https://api.eu.amazonalexa.com/v3/events
filter:
include_entities:
- light.light_switch_0
exclude_entities:
- light.light_switch_2
entity_config:
light.light_switch_0:
name: "Licht"
Step 5: Enable and Test the Alexa Skill
After the setup is completed you can enable and test your Alexa Home Assistant integration as a last step of this guide.
Enable the Skill
Open the Alexa app on your smartphone and enable the created developer skill using your Home Assistant credentials.
Issue Debugging
- Check logs in AWS Lambda for any errors.
- Monitor Home Assistant logs for invalid authentication attempts.
- Ensure the redirect URLs are correctly configured in both Alexa and Home Assistant.
Conclusion
Following these steps, you can successfully integrate Alexa with your self-hosted Home Assistant instance. This setup provides a seamless way to control your smart home using voice commands while maintaining full control over your data. You can also include scripts and all kinds of devices to be controlled using Alexa.