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 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')) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Refer the step by step to implement Alexa skil bridge
at
https://alexa_skill_bridge_lambda
The Checklist for your guys in the past and the future for the record.
(If you don't pass thru below checklist any of bit, you cannot get the own Alexa skill link.)
[pre-requisition]
Check HA address that your own domain or dynamic DNS(DDNS) or even IP
Prepare sure SSL certification that the free Let'sencrypt or free self-signed or commercial SSL cert if you would like.
Set the SSL cert on your server for HTTPS. And make sure SSL properly applied.
Set Alexa configuration in configuration.xml. Start simple and fill up later after link. Make problem simple for linkage.
Create AWS account
Choose the AWS Lambda region that N.Virginia or Oregon or EU that related to your Alexa language locale. AWS Alexa service will automatically find your Lambda region geologically by judging your Alexa locale.
Just copy & paste the source code into the Lambda(s) from Matt2005 at https://gist.github.com/matt2005/744b5ef548cc13d88d0569eea65f5e5b (thanks)
Create AWS Alexa Developer Account
Create AWS Alexa Skill for your own HA linkage as the materials
Put the endpoint address into the Alexa skill setting(as only default if you only have one, or set multiply each by check the checkbox.)
Setup the Lambdas's trigger as Alexa
READ carefully ALL the MATERIALS regards above to complete the section for 'Lambda' and 'Skill' both.(above are only simple summary)
Stop/cut and logout the home asisstant's(by nabucase.net) cloud annual payment service from the HA settings if you have.
[To get account link(important part)]
by test POST https://your_ha-domain_name/api/alexa/smart_home from lambda source code that any of response working. If you can see 40x on web browser, you will be fine.
which means that allow every URL paths in your firewall and NginX for HA.
Get your final external address, and set into all BASE_URL of environment variables & every in AWS Alexa console, AWS Lambeda, NginX, etc that port 443 without ':xxxx' part for your HA address.
If your SSL cert is free one, make sure your skill as in 'DEV' mode on the Alexa console where listed. If you have commercial no matter what dev or production mode.
Go to Alexa app or web > go to skill list > find your skill in DEV or peroper tab > click the skill you made > 'Enable' > Now login into HA(doesn't matter MFA or not) > TADA! you can see beautiful green 'successfully linked' message.
(if you cannot, it might firewall or any network path issue that blocked to reach to HA. So go back and recheck again.)
[Wait discovery(which Automatic drive)]
IF you already have discovered devices list in the Alexa app by another Alexa link service,
the app will tell you 'NO NEW device discovered' that nothing wrong since there are NO MORE NEW devices to discover.
or
if you are very new to link-up with Alexa, after discovery while, you can see all the devices on your Alexa app.
Walla!. All your from now.
[Addition]
[Summary]
[Q & A]